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;
195 * DLL head for key loading contexts
197 static struct KeyLoadContext *kl_head;
200 * DLL tail for key loading contexts
202 static struct KeyLoadContext *kl_tail;
204 struct KeyLoadContext
206 struct KeyLoadContext *next;
207 struct KeyLoadContext *prev;
208 struct GNUNET_CRYPTO_RsaKeyGenerationContext *keygen;
210 unsigned int *counter;
216 * Writes the encrypted private key of a zone in a file
218 * @param filename where to store the zone
219 * @param c the crypto container containing private key of the zone
220 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
223 write_key_to_file (const char *filename,
224 struct GNUNET_NAMESTORE_CryptoContainer *c)
226 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
227 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
228 struct GNUNET_DISK_FileHandle *fd;
229 struct GNUNET_CRYPTO_ShortHashCode zone;
230 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
231 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
233 fd = GNUNET_DISK_file_open (filename,
234 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS,
235 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
236 if ( (NULL == fd) && (EEXIST == errno) )
238 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
241 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
242 _("Failed to write zone key to file `%s': %s\n"),
244 _("file exists but reading key failed"));
245 return GNUNET_SYSERR;
247 GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
248 GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
249 GNUNET_CRYPTO_rsa_key_free (privkey);
250 if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "File zone `%s' containing this key already exists\n",
254 GNUNET_short_h2s (&zone));
257 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
258 _("Failed to write zone key to file `%s': %s\n"),
260 _("file exists with different key"));
265 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
266 return GNUNET_SYSERR;
268 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
270 GNUNET_break (GNUNET_YES == GNUNET_DISK_file_close (fd));
271 return GNUNET_SYSERR;
273 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
274 GNUNET_assert (NULL != enc);
275 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
277 GNUNET_DISK_file_sync (fd);
278 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
279 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
280 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
282 "Stored zonekey for zone `%s' in file `%s'\n",
283 GNUNET_short_h2s(&c->zone), c->filename);
289 * Write allthe given zone key to disk and then removes the entry from the
290 * 'zonekeys' hash map.
293 * @param key zone key
294 * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
296 * @return GNUNET_OK to continue iteration
299 zone_to_disk_it (void *cls,
300 const struct GNUNET_HashCode *key,
303 struct GNUNET_NAMESTORE_CryptoContainer *c = value;
305 if (NULL == c->filename)
306 GNUNET_asprintf(&c->filename,
309 GNUNET_short_h2s (&c->zone));
310 (void) write_key_to_file(c->filename, c);
311 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
312 GNUNET_CRYPTO_rsa_key_free (c->privkey);
313 GNUNET_free (c->filename);
320 * Add the given private key to the set of private keys
321 * this namestore can use to sign records when needed.
323 * @param pkey private key to add to our list (reference will
324 * be taken over or freed and should not be used afterwards)
327 learn_private_key (struct GNUNET_CRYPTO_RsaPrivateKey *pkey)
329 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
330 struct GNUNET_HashCode long_hash;
331 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
332 struct GNUNET_NAMESTORE_CryptoContainer *cc;
334 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
335 GNUNET_CRYPTO_short_hash (&pub,
336 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
338 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
340 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
342 GNUNET_CRYPTO_rsa_key_free (pkey);
345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
346 "Received new private key for zone `%s'\n",
347 GNUNET_short_h2s(&pubkey_hash));
348 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
350 cc->zone = pubkey_hash;
351 GNUNET_assert (GNUNET_YES ==
352 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc,
353 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
358 * Returns the expiration time of the given block of records. The block
359 * expiration time is the expiration time of the block with smallest
362 * @param rd_count number of records given in 'rd'
363 * @param rd array of records
364 * @return absolute expiration time
366 static struct GNUNET_TIME_Absolute
367 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
370 struct GNUNET_TIME_Absolute expire;
371 struct GNUNET_TIME_Absolute at;
372 struct GNUNET_TIME_Relative rt;
375 return GNUNET_TIME_UNIT_ZERO_ABS;
376 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
377 for (c = 0; c < rd_count; c++)
379 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
381 rt.rel_value = rd[c].expiration_time;
382 at = GNUNET_TIME_relative_to_absolute (rt);
386 at.abs_value = rd[c].expiration_time;
388 expire = GNUNET_TIME_absolute_min (at, expire);
395 * Task run during shutdown.
401 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
403 struct GNUNET_NAMESTORE_ZoneIteration *no;
404 struct GNUNET_NAMESTORE_Client *nc;
405 struct KeyLoadContext *kl;
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
410 GNUNET_SERVER_notification_context_destroy (snc);
414 while (NULL != (kl = kl_head))
416 GNUNET_CONTAINER_DLL_remove (kl_head, kl_tail, kl);
417 if (NULL != kl->keygen)
418 GNUNET_CRYPTO_rsa_key_create_stop (kl->keygen);
419 GNUNET_free (kl->filename);
423 GNUNET_CONTAINER_multihashmap_iterate (zonekeys, &zone_to_disk_it, NULL);
424 GNUNET_CONTAINER_multihashmap_destroy (zonekeys);
426 while (NULL != (nc = client_head))
428 while (NULL != (no = nc->op_head))
430 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
433 GNUNET_SERVER_client_drop(nc->client);
434 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
437 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
438 GNUNET_free (db_lib_name);
440 GNUNET_free_non_null (zonefile_directory);
441 zonefile_directory = NULL;
446 * Lookup our internal data structure for a given client.
448 * @param client server client handle to use for the lookup
449 * @return our internal structure for the client, NULL if
450 * we do not have any yet
452 static struct GNUNET_NAMESTORE_Client *
453 client_lookup (struct GNUNET_SERVER_Client *client)
455 struct GNUNET_NAMESTORE_Client *nc;
457 GNUNET_assert (NULL != client);
458 for (nc = client_head; NULL != nc; nc = nc->next)
459 if (client == nc->client)
466 * Called whenever a client is disconnected.
467 * Frees our resources associated with that client.
470 * @param client identification of the client
473 client_disconnect_notification (void *cls,
474 struct GNUNET_SERVER_Client *client)
476 struct GNUNET_NAMESTORE_ZoneIteration *no;
477 struct GNUNET_NAMESTORE_Client *nc;
481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
482 "Client %p disconnected\n",
484 if (NULL == (nc = client_lookup (client)))
486 while (NULL != (no = nc->op_head))
488 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
491 GNUNET_SERVER_client_drop (nc->client);
492 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
498 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
501 * @param client GNUNET_SERVER_Client sending the message
502 * @param message unused
505 handle_start (void *cls,
506 struct GNUNET_SERVER_Client *client,
507 const struct GNUNET_MessageHeader *message)
509 struct GNUNET_NAMESTORE_Client *nc;
511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
512 "Client %p connected\n", client);
513 if (NULL != client_lookup (client))
516 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
519 nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
521 GNUNET_SERVER_notification_context_add (snc, client);
522 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc);
523 GNUNET_SERVER_client_keep (client);
524 GNUNET_SERVER_receive_done (client, GNUNET_OK);
529 * Context for name lookups passed from 'handle_lookup_name' to
530 * 'handle_lookup_name_it' as closure
532 struct LookupNameContext
535 * The client to send the response to
537 struct GNUNET_NAMESTORE_Client *nc;
542 const struct GNUNET_CRYPTO_ShortHashCode *zone;
550 * Operation id for the name lookup
555 * Requested specific record type
557 uint32_t record_type;
562 * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
564 * @param cls a 'struct LookupNameContext *' with information about the request
565 * @param zone_key zone key of the zone
566 * @param expire expiration time
568 * @param rd_count number of records
569 * @param rd array of records
570 * @param signature signature
573 handle_lookup_name_it (void *cls,
574 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
575 struct GNUNET_TIME_Absolute expire,
577 unsigned int rd_count,
578 const struct GNUNET_NAMESTORE_RecordData *rd,
579 const struct GNUNET_CRYPTO_RsaSignature *signature)
581 struct LookupNameContext *lnc = cls;
582 struct LookupNameResponseMessage *lnr_msg;
583 struct GNUNET_NAMESTORE_RecordData *rd_selected;
584 struct GNUNET_NAMESTORE_CryptoContainer *cc;
585 struct GNUNET_CRYPTO_RsaSignature *signature_new;
586 struct GNUNET_TIME_Absolute e;
587 struct GNUNET_TIME_Relative re;
588 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
589 struct GNUNET_HashCode long_hash;
596 int contains_signature;
601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
602 "Found %u records under name `%s'\n",
605 authoritative = GNUNET_NO;
606 signature_new = NULL;
608 if (NULL != zone_key)
610 GNUNET_CRYPTO_short_hash (zone_key,
611 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
613 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
614 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get (zonekeys, &long_hash)))
616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
617 "Am authoritative for zone `%s'\n",
618 GNUNET_short_h2s (&zone_key_hash));
619 authoritative = GNUNET_YES;
624 rd_modified = GNUNET_NO;
626 /* count records to copy */
627 for (c = 0; c < rd_count; c++)
629 if ( (GNUNET_YES == authoritative) &&
631 GNUNET_NAMESTORE_is_expired (&rd[c]) ) )
633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
634 "Skipping expired record\n");
637 if ( (GNUNET_NAMESTORE_TYPE_ANY == lnc->record_type) ||
638 (rd[c].record_type == lnc->record_type) )
639 copied_elements++; /* found matching record */
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
643 "Skipping non-mtaching record\n");
644 rd_modified = GNUNET_YES;
647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
648 "Found %u records with type %u for name `%s' in zone `%s'\n",
652 GNUNET_short_h2s(lnc->zone));
653 if (copied_elements > 0)
655 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
657 for (c = 0; c < rd_count; c++)
659 if ( (GNUNET_YES == authoritative) &&
661 GNUNET_NAMESTORE_is_expired (&rd[c])) )
663 if ( (GNUNET_NAMESTORE_TYPE_ANY == lnc->record_type) ||
664 (rd[c].record_type == lnc->record_type) )
666 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
668 GNUNET_break (GNUNET_YES == authoritative);
669 rd_modified = GNUNET_YES;
670 re.rel_value = rd[c].expiration_time;
671 e = GNUNET_TIME_relative_to_absolute (re);
675 e.abs_value = rd[c].expiration_time;
677 /* found matching record, copy and convert flags to public format */
678 rd_selected[copied_elements] = rd[c]; /* shallow copy! */
679 rd_selected[copied_elements].expiration_time = e.abs_value;
680 if (0 != (rd_selected[copied_elements].flags &
681 (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION | GNUNET_NAMESTORE_RF_AUTHORITY)))
683 rd_selected[copied_elements].flags &= ~ (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION |
684 GNUNET_NAMESTORE_RF_AUTHORITY);
685 rd_modified = GNUNET_YES;
691 rd_modified = GNUNET_YES;
698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
699 "Found %u matching records for name `%s' in zone `%s'\n",
702 GNUNET_short_h2s (lnc->zone));
703 contains_signature = GNUNET_NO;
704 if (copied_elements > 0)
706 if (GNUNET_YES == authoritative)
708 GNUNET_assert (NULL != cc);
709 e = get_block_expiration_time (rd_count, rd);
710 signature_new = GNUNET_NAMESTORE_create_signature (cc->privkey, e, name, rd_selected, copied_elements);
711 GNUNET_assert (NULL != signature_new);
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "Creating signature for name `%s' with %u records in zone `%s'\n",
716 GNUNET_short_h2s(&zone_key_hash));
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
721 "Not authoritative, records modified is %d, have sig is %d\n",
724 if ((GNUNET_NO == rd_modified) && (NULL != signature))
725 contains_signature = GNUNET_YES; /* returning all records, so include signature */
729 rd_ser_len = GNUNET_NAMESTORE_records_get_size (copied_elements, rd_selected);
730 name_len = (NULL == name) ? 0 : strlen(name) + 1;
731 r_size = sizeof (struct LookupNameResponseMessage) +
732 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
736 "Sending `%s' message\n",
737 "NAMESTORE_LOOKUP_NAME_RESPONSE");
738 lnr_msg = GNUNET_malloc (r_size);
739 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
740 lnr_msg->gns_header.header.size = ntohs (r_size);
741 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
742 lnr_msg->rd_count = htons (copied_elements);
743 lnr_msg->rd_len = htons (rd_ser_len);
744 lnr_msg->name_len = htons (name_len);
745 lnr_msg->expire = GNUNET_TIME_absolute_hton (get_block_expiration_time (copied_elements,
747 name_tmp = (char *) &lnr_msg[1];
748 memcpy (name_tmp, name, name_len);
749 rd_tmp = &name_tmp[name_len];
750 GNUNET_NAMESTORE_records_serialize (copied_elements, rd_selected, rd_ser_len, rd_tmp);
751 if (rd_selected != rd)
752 GNUNET_free_non_null (rd_selected);
753 if (NULL != zone_key)
754 lnr_msg->public_key = *zone_key;
755 if ( (GNUNET_YES == authoritative) &&
756 (copied_elements > 0) )
758 /* use new created signature */
759 lnr_msg->contains_sig = htons (GNUNET_YES);
760 GNUNET_assert (NULL != signature_new);
761 lnr_msg->signature = *signature_new;
762 GNUNET_free (signature_new);
764 else if (GNUNET_YES == contains_signature)
766 /* use existing signature */
767 lnr_msg->contains_sig = htons (GNUNET_YES);
768 GNUNET_assert (NULL != signature);
769 lnr_msg->signature = *signature;
771 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client,
772 &lnr_msg->gns_header.header,
774 GNUNET_free (lnr_msg);
779 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
782 * @param client GNUNET_SERVER_Client sending the message
783 * @param message message of type 'struct LookupNameMessage'
786 handle_lookup_name (void *cls,
787 struct GNUNET_SERVER_Client *client,
788 const struct GNUNET_MessageHeader *message)
790 const struct LookupNameMessage *ln_msg;
791 struct LookupNameContext lnc;
792 struct GNUNET_NAMESTORE_Client *nc;
798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
799 "Received `%s' message\n",
800 "NAMESTORE_LOOKUP_NAME");
801 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
804 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
807 if (NULL == (nc = client_lookup(client)))
810 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
813 ln_msg = (const struct LookupNameMessage *) message;
814 rid = ntohl (ln_msg->gns_header.r_id);
815 name_len = ntohl (ln_msg->name_len);
816 type = ntohl (ln_msg->record_type);
817 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
820 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
823 name = (const char *) &ln_msg[1];
824 if ('\0' != name[name_len -1])
827 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
830 if (GNUNET_NAMESTORE_TYPE_ANY == type)
831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
832 "Looking up all records for name `%s' in zone `%s'\n",
834 GNUNET_short_h2s(&ln_msg->zone));
836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
837 "Looking up records with type %u for name `%s' in zone `%s'\n",
839 GNUNET_short_h2s(&ln_msg->zone));
841 /* do the actual lookup */
842 lnc.request_id = rid;
844 lnc.record_type = type;
846 lnc.zone = &ln_msg->zone;
848 GSN_database->iterate_records (GSN_database->cls,
849 &ln_msg->zone, name, 0 /* offset */,
850 &handle_lookup_name_it, &lnc))
852 /* internal error (in database plugin); might be best to just hang up on
853 plugin rather than to signal that there are 'no' results, which
854 might also be false... */
856 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
859 GNUNET_SERVER_receive_done (client, GNUNET_OK);
864 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
867 * @param client GNUNET_SERVER_Client sending the message
868 * @param message message of type 'struct RecordPutMessage'
871 handle_record_put (void *cls,
872 struct GNUNET_SERVER_Client *client,
873 const struct GNUNET_MessageHeader *message)
875 struct GNUNET_NAMESTORE_Client *nc;
876 const struct RecordPutMessage *rp_msg;
877 struct GNUNET_TIME_Absolute expire;
878 const struct GNUNET_CRYPTO_RsaSignature *signature;
879 struct RecordPutResponseMessage rpr_msg;
880 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
892 "Received `%s' message\n",
893 "NAMESTORE_RECORD_PUT");
894 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
897 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
900 if (NULL == (nc = client_lookup (client)))
903 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
906 rp_msg = (const struct RecordPutMessage *) message;
907 rid = ntohl (rp_msg->gns_header.r_id);
908 msg_size = ntohs (rp_msg->gns_header.header.size);
909 name_len = ntohs (rp_msg->name_len);
910 rd_count = ntohs (rp_msg->rd_count);
911 rd_ser_len = ntohs (rp_msg->rd_len);
912 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >= MAX_NAME_LEN) || (0 == name_len))
915 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
918 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
919 if (msg_size != msg_size_exp)
922 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
925 name = (const char *) &rp_msg[1];
926 if ('\0' != name[name_len -1])
929 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
932 expire = GNUNET_TIME_absolute_ntoh (rp_msg->expire);
933 signature = &rp_msg->signature;
934 rd_ser = &name[name_len];
936 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
939 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
942 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
945 GNUNET_CRYPTO_short_hash (&rp_msg->public_key,
946 sizeof (rp_msg->public_key),
948 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
949 "Putting %u records under name `%s' in zone `%s'\n",
951 GNUNET_short_h2s (&zone_hash));
952 res = GSN_database->put_records(GSN_database->cls,
958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
959 "Putting record for name `%s': %s\n",
961 (GNUNET_OK == res) ? "OK" : "FAILED");
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
964 "Sending `%s' message\n",
965 "RECORD_PUT_RESPONSE");
966 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
967 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
968 rpr_msg.gns_header.r_id = htonl (rid);
969 rpr_msg.op_result = htonl (res);
970 GNUNET_SERVER_notification_context_unicast (snc,
972 &rpr_msg.gns_header.header,
974 GNUNET_SERVER_receive_done (client, GNUNET_OK);
979 * Context for record create operations passed from 'handle_record_create' to
980 * 'handle_create_record_it' as closure
982 struct CreateRecordContext
987 const struct GNUNET_NAMESTORE_RecordData *rd;
992 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
995 * Name for the record to create
1000 * Record expiration time
1002 struct GNUNET_TIME_Absolute expire;
1005 * result returned from 'handle_create_record_it'
1006 * GNUNET_SYSERR: failed to create the record
1007 * GNUNET_NO: we updated an existing record or identical entry existed
1008 * GNUNET_YES : we created a new record
1015 * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
1016 * in handle_record_create
1018 * @param cls a 'struct CreateRecordContext *' with information about the request
1019 * @param pubkey zone key of the zone
1020 * @param expire expiration time
1022 * @param rd_count number of records
1023 * @param rd array of records
1024 * @param signature signature
1027 handle_create_record_it (void *cls,
1028 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
1029 struct GNUNET_TIME_Absolute expire,
1031 unsigned int rd_count,
1032 const struct GNUNET_NAMESTORE_RecordData *rd,
1033 const struct GNUNET_CRYPTO_RsaSignature *signature)
1035 static struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1036 struct CreateRecordContext *crc = cls;
1037 struct GNUNET_NAMESTORE_RecordData *rd_new;
1038 struct GNUNET_TIME_Absolute block_expiration;
1042 unsigned int rd_count_new;
1044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1045 "Found %u existing records for `%s'\n",
1046 rd_count, crc->name);
1049 for (c = 0; c < rd_count; c++)
1051 if ( (crc->rd->record_type != rd[c].record_type) ||
1052 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
1053 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1054 continue; /* no match */
1055 if ( (GNUNET_NAMESTORE_TYPE_PKEY == crc->rd->record_type) ||
1056 (GNUNET_NAMESTORE_TYPE_PSEU == crc->rd->record_type) ||
1057 (GNUNET_DNSPARSER_TYPE_CNAME == crc->rd->record_type) )
1059 /* Update unique PKEY, PSEU or CNAME record; for these
1060 record types, only one can be active at any time */
1062 if ( (crc->rd->data_size != rd[c].data_size) ||
1063 (0 != memcmp (crc->rd->data, rd[c].data, rd[c].data_size)) ||
1064 (crc->rd->expiration_time != rd[c].expiration_time) )
1065 update = GNUNET_YES;
1068 if ( (crc->rd->data_size == rd[c].data_size) &&
1069 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
1071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1072 "Found matching existing record for `%s'; only updating expiration date!\n",
1075 if (crc->rd->expiration_time != rd[c].expiration_time)
1076 update = GNUNET_YES;
1081 if ( (-1 != exist) &&
1082 (GNUNET_NO == update) )
1084 /* Exact same record already exists */
1085 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1086 "Matching record for %s' exists, no change required!\n",
1088 crc->res = GNUNET_NO; /* identical record existed */
1093 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094 "No existing record for name `%s'!\n",
1096 rd_count_new = rd_count + 1;
1097 rd_new = GNUNET_malloc (rd_count_new * sizeof (struct GNUNET_NAMESTORE_RecordData));
1098 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1099 rd_new[rd_count] = *(crc->rd);
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "Updating existing records for `%s'!\n",
1106 rd_count_new = rd_count;
1107 rd_new = GNUNET_malloc (rd_count_new * sizeof (struct GNUNET_NAMESTORE_RecordData));
1108 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1109 rd_new[exist] = *(crc->rd);
1111 block_expiration = GNUNET_TIME_absolute_max (crc->expire, expire);
1113 GSN_database->put_records (GSN_database->cls,
1117 rd_count_new, rd_new,
1119 crc->res = GNUNET_SYSERR; /* error */
1120 else if (GNUNET_YES == update)
1121 crc->res = GNUNET_NO; /* update */
1123 crc->res = GNUNET_YES; /* created new record */
1124 GNUNET_free (rd_new);
1129 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1132 * @param client GNUNET_SERVER_Client sending the message
1133 * @param message message of type 'struct RecordCreateMessage'
1136 handle_record_create (void *cls,
1137 struct GNUNET_SERVER_Client *client,
1138 const struct GNUNET_MessageHeader *message)
1140 struct GNUNET_NAMESTORE_Client *nc;
1141 const struct RecordCreateMessage *rp_msg;
1142 struct CreateRecordContext crc;
1143 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1144 struct RecordCreateResponseMessage rcr_msg;
1147 size_t msg_size_exp;
1151 const char *pkey_tmp;
1152 const char *name_tmp;
1154 unsigned int rd_count;
1156 struct GNUNET_NAMESTORE_RecordData rd;
1157 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1160 "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1161 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1164 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1167 if (NULL == (nc = client_lookup (client)))
1170 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1173 rp_msg = (const struct RecordCreateMessage *) message;
1174 rid = ntohl (rp_msg->gns_header.r_id);
1175 name_len = ntohs (rp_msg->name_len);
1176 msg_size = ntohs (message->size);
1177 rd_count = ntohs (rp_msg->rd_count);
1178 rd_ser_len = ntohs (rp_msg->rd_len);
1179 key_len = ntohs (rp_msg->pkey_len);
1180 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1181 if ( (msg_size != msg_size_exp) || (1 != rd_count) )
1184 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1187 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1190 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1193 pkey_tmp = (const char *) &rp_msg[1];
1194 name_tmp = &pkey_tmp[key_len];
1195 rd_ser = &name_tmp[name_len];
1196 if ('\0' != name_tmp[name_len -1])
1199 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1202 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1205 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1209 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, &rd))
1212 GNUNET_CRYPTO_rsa_key_free (pkey);
1213 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1217 /* Extracting and converting private key */
1218 GNUNET_CRYPTO_rsa_key_get_public (pkey, &crc.pubkey);
1219 GNUNET_CRYPTO_short_hash (&crc.pubkey,
1220 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1222 learn_private_key (pkey);
1223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1224 "Creating record for name `%s' in zone `%s'\n",
1225 name_tmp, GNUNET_short_h2s(&pubkey_hash));
1226 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1227 crc.res = GNUNET_SYSERR;
1229 crc.name = name_tmp;
1231 /* Get existing records for name */
1232 res = GSN_database->iterate_records (GSN_database->cls, &pubkey_hash, name_tmp, 0,
1233 &handle_create_record_it, &crc);
1234 if (res != GNUNET_SYSERR)
1238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1239 "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1240 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1241 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1242 rcr_msg.gns_header.r_id = htonl (rid);
1243 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1244 rcr_msg.op_result = htonl (GNUNET_YES);
1245 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1246 rcr_msg.op_result = htonl (GNUNET_NO);
1248 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1249 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
1250 &rcr_msg.gns_header.header,
1252 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1257 * Context for record remove operations passed from 'handle_record_remove' to
1258 * 'handle_record_remove_it' as closure
1260 struct RemoveRecordContext
1265 const struct GNUNET_NAMESTORE_RecordData *rd;
1268 * See RECORD_REMOVE_RESULT_*-codes. Set by 'handle_record_remove_it'
1269 * to the result of the operation.
1276 * We are to remove a record (or all records for a given name). This function
1277 * will be called with the existing records (if there are any) and is to then
1278 * compute what to keep and trigger the necessary changes.
1280 * @param cls the 'struct RecordRemoveContext' with information about what to remove
1281 * @param zone_key public key of the zone
1282 * @param expire when does the corresponding block in the DHT expire (until
1283 * when should we never do a DHT lookup for the same name again)?
1284 * @param name name that is being mapped (at most 255 characters long)
1285 * @param rd_count number of entries in 'rd' array
1286 * @param rd array of records with data to store
1287 * @param signature signature of the record block, NULL if signature is unavailable (i.e.
1288 * because the user queried for a particular record type only)
1291 handle_record_remove_it (void *cls,
1292 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1293 struct GNUNET_TIME_Absolute expire,
1295 unsigned int rd_count,
1296 const struct GNUNET_NAMESTORE_RecordData *rd,
1297 const struct GNUNET_CRYPTO_RsaSignature *signature)
1299 static struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1300 struct RemoveRecordContext *rrc = cls;
1303 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306 "Name `%s 'currently has %u records\n",
1310 /* Could not find record to remove */
1311 rrc->op_res = RECORD_REMOVE_RESULT_NO_RECORDS;
1314 /* Find record to remove */
1316 for (c = 0; c < rd_count; c++)
1319 GNUNET_NAMESTORE_records_cmp (&rd[c],
1322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1328 /* Could not find record to remove */
1329 rrc->op_res = RECORD_REMOVE_RESULT_RECORD_NOT_FOUND;
1334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1335 "No records left for name `%s', removing name\n",
1337 GNUNET_CRYPTO_short_hash (zone_key,
1338 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1341 GSN_database->remove_records (GSN_database->cls,
1345 /* Could not remove records from database */
1346 rrc->op_res = RECORD_REMOVE_RESULT_FAILED_TO_REMOVE;
1349 rrc->op_res = RECORD_REMOVE_RESULT_SUCCESS;
1354 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count - 1];
1355 unsigned int c2 = 0;
1357 for (c = 0; c < rd_count; c++)
1361 rd_new[c2++] = rd[c];
1364 GSN_database->put_records(GSN_database->cls,
1368 rd_count - 1, rd_new,
1371 /* Could not put records into database */
1372 rrc->op_res = RECORD_REMOVE_RESULT_FAILED_TO_PUT_UPDATE;
1376 rrc->op_res = RECORD_REMOVE_RESULT_SUCCESS;
1381 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1384 * @param client GNUNET_SERVER_Client sending the message
1385 * @param message message of type 'struct RecordRemoveMessage'
1388 handle_record_remove (void *cls,
1389 struct GNUNET_SERVER_Client *client,
1390 const struct GNUNET_MessageHeader *message)
1392 struct GNUNET_NAMESTORE_Client *nc;
1393 const struct RecordRemoveMessage *rr_msg;
1394 struct RecordRemoveResponseMessage rrr_msg;
1395 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1396 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1397 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1398 struct GNUNET_NAMESTORE_RecordData rd;
1399 const char *pkey_tmp;
1400 const char *name_tmp;
1406 size_t msg_size_exp;
1409 struct RemoveRecordContext rrc;
1413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1414 "Received `%s' message\n",
1415 "NAMESTORE_RECORD_REMOVE");
1416 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1419 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1422 if (NULL == (nc = client_lookup(client)))
1425 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1428 rr_msg = (const struct RecordRemoveMessage *) message;
1429 rid = ntohl (rr_msg->gns_header.r_id);
1430 name_len = ntohs (rr_msg->name_len);
1431 rd_ser_len = ntohs (rr_msg->rd_len);
1432 rd_count = ntohs (rr_msg->rd_count);
1433 key_len = ntohs (rr_msg->pkey_len);
1434 msg_size = ntohs (message->size);
1435 if ((name_len >= MAX_NAME_LEN) || (0 == name_len) || (1 < rd_count) )
1438 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1441 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1442 if (msg_size != msg_size_exp)
1445 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1448 pkey_tmp = (const char *) &rr_msg[1];
1449 name_tmp = &pkey_tmp[key_len];
1450 rd_ser = &name_tmp[name_len];
1451 if ('\0' != name_tmp[name_len -1])
1454 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1457 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1460 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1463 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
1464 GNUNET_CRYPTO_short_hash (&pub,
1465 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1467 learn_private_key (pkey);
1469 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, &rd))
1472 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1478 /* remove the whole name and all records */
1479 res = GSN_database->remove_records (GSN_database->cls,
1482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1483 "Removing name `%s': %s\n",
1484 name_tmp, (GNUNET_OK == res) ? "OK" : "FAILED");
1485 if (GNUNET_OK != res)
1486 /* Could not remove entry from database */
1487 res = RECORD_REMOVE_RESULT_FAILED_TO_PUT_UPDATE;
1489 res = RECORD_REMOVE_RESULT_SUCCESS;
1493 /* remove a single record */
1494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1495 "Removing record for name `%s' in zone `%s'\n", name_tmp,
1496 GNUNET_short_h2s (&pubkey_hash));
1498 rrc.op_res = RECORD_REMOVE_RESULT_RECORD_NOT_FOUND;
1501 while ( (RECORD_REMOVE_RESULT_RECORD_NOT_FOUND == rrc.op_res) &&
1502 (GNUNET_OK == res) )
1504 res = GSN_database->iterate_records (GSN_database->cls,
1508 &handle_record_remove_it, &rrc);
1516 GNUNET_break (RECORD_REMOVE_RESULT_NO_RECORDS == rrc.op_res);
1517 res = RECORD_REMOVE_RESULT_NO_RECORDS;
1518 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1519 _("Failed to find record to remove\n"));
1522 res = RECORD_REMOVE_RESULT_FAILED_ACCESS_DATABASE;
1526 res = RECORD_REMOVE_RESULT_FAILED_INTERNAL_ERROR;
1530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1531 "Sending `%s' message\n",
1532 "RECORD_REMOVE_RESPONSE");
1533 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1534 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1535 rrr_msg.gns_header.r_id = htonl (rid);
1536 rrr_msg.op_result = htonl (res);
1537 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
1538 &rrr_msg.gns_header.header,
1540 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1545 * Context for record remove operations passed from 'handle_zone_to_name' to
1546 * 'handle_zone_to_name_it' as closure
1548 struct ZoneToNameCtx
1553 struct GNUNET_NAMESTORE_Client *nc;
1556 * Request id (to be used in the response to the client).
1561 * Set to GNUNET_OK on success, GNUNET_SYSERR on error. Note that
1562 * not finding a name for the zone still counts as a 'success' here,
1563 * as this field is about the success of executing the IPC protocol.
1570 * Zone to name iterator
1572 * @param cls struct ZoneToNameCtx *
1573 * @param zone_key the zone key
1574 * @param expire expiration date
1576 * @param rd_count number of records
1577 * @param rd record data
1578 * @param signature signature
1581 handle_zone_to_name_it (void *cls,
1582 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1583 struct GNUNET_TIME_Absolute expire,
1585 unsigned int rd_count,
1586 const struct GNUNET_NAMESTORE_RecordData *rd,
1587 const struct GNUNET_CRYPTO_RsaSignature *signature)
1589 struct ZoneToNameCtx *ztn_ctx = cls;
1590 struct ZoneToNameResponseMessage *ztnr_msg;
1599 if ((NULL != zone_key) && (NULL != name))
1602 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1603 "Found result: name `%s' has %u records\n",
1606 name_len = strlen (name) + 1;
1610 /* no result found */
1611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1612 "Found no results\n");
1616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1617 "Sending `%s' message\n",
1618 "ZONE_TO_NAME_RESPONSE");
1619 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1620 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1621 if (NULL != signature)
1622 msg_size += sizeof (struct GNUNET_CRYPTO_RsaSignature);
1623 if (msg_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1626 ztn_ctx->success = GNUNET_SYSERR;
1629 ztnr_msg = GNUNET_malloc (msg_size);
1630 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1631 ztnr_msg->gns_header.header.size = htons (msg_size);
1632 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1633 ztnr_msg->res = htons (res);
1634 ztnr_msg->rd_len = htons (rd_ser_len);
1635 ztnr_msg->rd_count = htons (rd_count);
1636 ztnr_msg->name_len = htons (name_len);
1637 ztnr_msg->expire = GNUNET_TIME_absolute_hton (expire);
1638 if (NULL != zone_key)
1639 ztnr_msg->zone_key = *zone_key;
1640 name_tmp = (char *) &ztnr_msg[1];
1642 memcpy (name_tmp, name, name_len);
1643 rd_tmp = &name_tmp[name_len];
1644 GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_tmp);
1645 sig_tmp = &rd_tmp[rd_ser_len];
1646 if (NULL != signature)
1647 memcpy (sig_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature));
1648 ztn_ctx->success = GNUNET_OK;
1649 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client,
1650 &ztnr_msg->gns_header.header,
1652 GNUNET_free (ztnr_msg);
1657 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1660 * @param client GNUNET_SERVER_Client sending the message
1661 * @param message message of type 'struct ZoneToNameMessage'
1664 handle_zone_to_name (void *cls,
1665 struct GNUNET_SERVER_Client *client,
1666 const struct GNUNET_MessageHeader *message)
1668 struct GNUNET_NAMESTORE_Client *nc;
1669 const struct ZoneToNameMessage *ztn_msg;
1670 struct ZoneToNameCtx ztn_ctx;
1672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1673 "Received `%s' message\n",
1675 ztn_msg = (const struct ZoneToNameMessage *) message;
1676 if (NULL == (nc = client_lookup(client)))
1679 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1682 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1684 ztn_ctx.success = GNUNET_SYSERR;
1685 if (GNUNET_SYSERR ==
1686 GSN_database->zone_to_name (GSN_database->cls,
1688 &ztn_msg->value_zone,
1689 &handle_zone_to_name_it, &ztn_ctx))
1691 /* internal error, hang up instead of signalling something
1692 that might be wrong */
1694 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1697 GNUNET_SERVER_receive_done (client, ztn_ctx.success);
1702 * Zone iteration processor result
1704 enum ZoneIterationResult
1707 * Found records, but all records were filtered
1708 * Continue to iterate
1710 IT_ALL_RECORDS_FILTERED = -1,
1714 * Continue to iterate with next iteration_next call
1716 IT_SUCCESS_MORE_AVAILABLE = 0,
1719 * Iteration complete
1721 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 1
1726 * Context for record remove operations passed from
1727 * 'run_zone_iteration_round' to 'zone_iteraterate_proc' as closure
1729 struct ZoneIterationProcResult
1732 * The zone iteration handle
1734 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1737 * Iteration result: iteration done?
1738 * IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
1739 * we got one for now and have sent it to the client
1740 * IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
1741 * IT_ALL_RECORDS_FILTERED: if all results were filtered so far.
1743 int res_iteration_finished;
1749 * Process results for zone iteration from database
1751 * @param cls struct ZoneIterationProcResult *proc
1752 * @param zone_key the zone key
1753 * @param expire expiration time
1755 * @param rd_count number of records for this name
1756 * @param rd record data
1757 * @param signature block signature
1760 zone_iteraterate_proc (void *cls,
1761 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1762 struct GNUNET_TIME_Absolute expire,
1764 unsigned int rd_count,
1765 const struct GNUNET_NAMESTORE_RecordData *rd,
1766 const struct GNUNET_CRYPTO_RsaSignature *signature)
1768 struct ZoneIterationProcResult *proc = cls;
1769 struct GNUNET_NAMESTORE_RecordData rd_filtered[rd_count];
1770 struct GNUNET_CRYPTO_RsaSignature *new_signature = NULL;
1771 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1772 struct GNUNET_HashCode long_hash;
1773 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1774 struct ZoneIterationResponseMessage *zir_msg;
1775 struct GNUNET_TIME_Relative rt;
1776 unsigned int rd_count_filtered;
1784 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1785 if ((NULL == zone_key) && (NULL == name))
1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1788 "Iteration done\n");
1789 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1792 if ((NULL == zone_key) || (NULL == name))
1794 /* what is this!? should never happen */
1798 rd_count_filtered = 0;
1799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1800 "Received result for zone iteration: `%s'\n",
1802 for (c = 0; c < rd_count; c++)
1804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1805 "Record %u has flags: %x must have flags are %x, must not have flags are %x\n",
1807 proc->zi->must_have_flags,
1808 proc->zi->must_not_have_flags);
1809 /* Checking must have flags, except 'relative-expiration' which is a special flag */
1810 if ((rd[c].flags & proc->zi->must_have_flags & (~GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
1811 != (proc->zi->must_have_flags & (~ GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)))
1813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %u lacks 'must-have' flags: Not included\n", c);
1816 /* Checking must-not-have flags */
1817 if (0 != (rd[c].flags & proc->zi->must_not_have_flags))
1819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1820 "Record %u has 'must-not-have' flags: Not included\n", c);
1823 rd_filtered[rd_count_filtered] = rd[c];
1824 /* convert relative to absolute expiration time unless explicitly requested otherwise */
1825 if ( (0 == (proc->zi->must_have_flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) &&
1826 (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1828 /* should convert relative-to-absolute expiration time */
1829 rt.rel_value = rd[c].expiration_time;
1830 rd_filtered[c].expiration_time = GNUNET_TIME_relative_to_absolute (rt).abs_value;
1831 rd_filtered[c].flags &= ~ GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
1833 /* we NEVER keep the 'authority' flag */
1834 rd_filtered[c].flags &= ~ GNUNET_NAMESTORE_RF_AUTHORITY;
1835 rd_count_filtered++;
1837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1838 "Included %u of %u records\n",
1839 rd_count_filtered, rd_count);
1842 if ( (rd_count_filtered > 0) &&
1843 (0 == (proc->zi->must_have_flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1845 /* compute / obtain signature, but only if we (a) have records and (b) expiration times were
1846 converted to absolute expiration times */
1847 GNUNET_CRYPTO_short_hash (zone_key,
1848 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1850 GNUNET_CRYPTO_short_hash_double (&zone_hash, &long_hash);
1851 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash)))
1853 expire = get_block_expiration_time (rd_count_filtered, rd_filtered);
1854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1855 "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1856 name, GNUNET_short_h2s(&zone_hash),
1858 (unsigned long long) expire.abs_value);
1859 new_signature = GNUNET_NAMESTORE_create_signature (cc->privkey, expire, name,
1860 rd_filtered, rd_count_filtered);
1861 GNUNET_assert (NULL != new_signature);
1862 signature = new_signature;
1864 else if (rd_count_filtered == rd_count)
1866 if (NULL != signature)
1868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1869 "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1870 name, GNUNET_short_h2s (&zone_hash), rd_count_filtered,
1871 (unsigned long long) expire.abs_value);
1876 if (rd_count_filtered == 0)
1878 /* After filtering records there are no records left to return */
1879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No records to transmit\n");
1880 proc->res_iteration_finished = IT_ALL_RECORDS_FILTERED;
1884 if (GNUNET_YES == proc->zi->has_zone)
1885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1886 "Sending name `%s' for iteration over zone `%s'\n",
1887 name, GNUNET_short_h2s(&proc->zi->zone));
1889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1890 "Sending name `%s' for iteration over all zones\n",
1892 name_len = strlen (name) + 1;
1893 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count_filtered, rd_filtered);
1894 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1896 zir_msg = GNUNET_malloc (msg_size);
1897 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1898 zir_msg->gns_header.header.size = htons (msg_size);
1899 zir_msg->gns_header.r_id = htonl (proc->zi->request_id);
1900 zir_msg->expire = GNUNET_TIME_absolute_hton (expire);
1901 zir_msg->reserved = htons (0);
1902 zir_msg->name_len = htons (name_len);
1903 zir_msg->rd_count = htons (rd_count_filtered);
1904 zir_msg->rd_len = htons (rd_ser_len);
1905 if (NULL != signature)
1906 zir_msg->signature = *signature;
1907 zir_msg->public_key = *zone_key;
1908 name_tmp = (char *) &zir_msg[1];
1909 memcpy (name_tmp, name, name_len);
1910 rd_ser = &name_tmp[name_len];
1911 GNUNET_NAMESTORE_records_serialize (rd_count_filtered, rd_filtered, rd_ser_len, rd_ser);
1912 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1913 "Sending `%s' message with size %u\n",
1914 "ZONE_ITERATION_RESPONSE",
1916 GNUNET_SERVER_notification_context_unicast (snc, proc->zi->client->client,
1917 (const struct GNUNET_MessageHeader *) zir_msg,
1919 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1920 GNUNET_free (zir_msg);
1921 GNUNET_free_non_null (new_signature);
1926 * Perform the next round of the zone iteration.
1928 * @param zi zone iterator to process
1931 run_zone_iteration_round (struct GNUNET_NAMESTORE_ZoneIteration *zi)
1933 struct ZoneIterationProcResult proc;
1934 struct ZoneIterationResponseMessage zir_end;
1935 struct GNUNET_CRYPTO_ShortHashCode *zone;
1937 memset (&proc, 0, sizeof (proc));
1939 if (GNUNET_YES == zi->has_zone)
1943 proc.res_iteration_finished = IT_ALL_RECORDS_FILTERED;
1944 while (IT_ALL_RECORDS_FILTERED == proc.res_iteration_finished)
1946 if (GNUNET_SYSERR ==
1947 GSN_database->iterate_records (GSN_database->cls, zone, NULL,
1949 &zone_iteraterate_proc, &proc))
1956 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1959 "More results available\n");
1960 return; /* more results later */
1962 if (GNUNET_YES == zi->has_zone)
1963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1964 "No more results for zone `%s'\n",
1965 GNUNET_short_h2s(&zi->zone));
1967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1968 "No more results for all zones\n");
1969 memset (&zir_end, 0, sizeof (zir_end));
1970 zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1971 zir_end.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1972 zir_end.gns_header.r_id = htonl(zi->request_id);
1973 GNUNET_SERVER_notification_context_unicast (snc,
1975 &zir_end.gns_header.header, GNUNET_NO);
1976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1977 "Removing zone iterator\n");
1978 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1984 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
1987 * @param client GNUNET_SERVER_Client sending the message
1988 * @param message message of type 'struct ZoneIterationStartMessage'
1991 handle_iteration_start (void *cls,
1992 struct GNUNET_SERVER_Client *client,
1993 const struct GNUNET_MessageHeader *message)
1995 static struct GNUNET_CRYPTO_ShortHashCode zeros;
1996 const struct ZoneIterationStartMessage *zis_msg;
1997 struct GNUNET_NAMESTORE_Client *nc;
1998 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2001 if (NULL == (nc = client_lookup (client)))
2004 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2007 zis_msg = (const struct ZoneIterationStartMessage *) message;
2008 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2009 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2012 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2013 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2014 if (0 == memcmp (&zeros, &zis_msg->zone, sizeof (zeros)))
2016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2017 zi->zone = zis_msg->zone;
2018 zi->has_zone = GNUNET_NO;
2022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2023 "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2024 zi->zone = zis_msg->zone;
2025 zi->has_zone = GNUNET_YES;
2027 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2028 run_zone_iteration_round (zi);
2029 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2034 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2037 * @param client GNUNET_SERVER_Client sending the message
2038 * @param message message of type 'struct ZoneIterationStopMessage'
2041 handle_iteration_stop (void *cls,
2042 struct GNUNET_SERVER_Client *client,
2043 const struct GNUNET_MessageHeader *message)
2045 struct GNUNET_NAMESTORE_Client *nc;
2046 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2047 const struct ZoneIterationStopMessage *zis_msg;
2050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2051 "Received `%s' message\n",
2052 "ZONE_ITERATION_STOP");
2053 if (NULL == (nc = client_lookup(client)))
2056 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2059 zis_msg = (const struct ZoneIterationStopMessage *) message;
2060 rid = ntohl (zis_msg->gns_header.r_id);
2061 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2062 if (zi->request_id == rid)
2067 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2070 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2071 if (GNUNET_YES == zi->has_zone)
2072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2073 "Stopped zone iteration for zone `%s'\n",
2074 GNUNET_short_h2s (&zi->zone));
2076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2077 "Stopped zone iteration over all zones\n");
2079 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2084 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT' message
2087 * @param client GNUNET_SERVER_Client sending the message
2088 * @param message message of type 'struct ZoneIterationNextMessage'
2091 handle_iteration_next (void *cls,
2092 struct GNUNET_SERVER_Client *client,
2093 const struct GNUNET_MessageHeader *message)
2095 struct GNUNET_NAMESTORE_Client *nc;
2096 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2097 const struct ZoneIterationNextMessage *zis_msg;
2100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2101 if (NULL == (nc = client_lookup(client)))
2104 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2107 zis_msg = (const struct ZoneIterationNextMessage *) message;
2108 rid = ntohl (zis_msg->gns_header.r_id);
2109 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2110 if (zi->request_id == rid)
2115 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2118 run_zone_iteration_round (zi);
2119 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2123 zonekey_it_key_cb (void *cls,
2124 struct GNUNET_CRYPTO_RsaPrivateKey *pk,
2127 struct KeyLoadContext *kl = cls;
2132 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2133 _("Could not parse zone key file `%s'\n"),
2137 learn_private_key (pk);
2140 GNUNET_CONTAINER_DLL_remove (kl_head, kl_tail, kl);
2141 GNUNET_free (kl->filename);
2147 * Load zone keys from directory by reading all .zkey files in this directory
2149 * @param cls int * 'counter' to store the number of files found
2150 * @param filename directory to scan
2151 * @return GNUNET_OK to continue
2154 zonekey_file_it (void *cls, const char *filename)
2156 struct KeyLoadContext *kl;
2158 if ((NULL == filename) ||
2159 (NULL == strstr(filename, ".zkey")))
2162 kl = GNUNET_malloc (sizeof (struct KeyLoadContext));
2163 kl->filename = strdup (filename);
2165 kl->keygen = GNUNET_CRYPTO_rsa_key_create_start (filename, zonekey_it_key_cb, kl);
2166 if (NULL == kl->keygen)
2168 GNUNET_free (kl->filename);
2173 GNUNET_CONTAINER_DLL_insert (kl_head, kl_tail, kl);
2179 * Process namestore requests.
2181 * @param cls closure
2182 * @param server the initialized server
2183 * @param cfg configuration to use
2186 run (void *cls, struct GNUNET_SERVER_Handle *server,
2187 const struct GNUNET_CONFIGURATION_Handle *cfg)
2189 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2190 {&handle_start, NULL,
2191 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2192 {&handle_lookup_name, NULL,
2193 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2194 {&handle_record_put, NULL,
2195 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2196 {&handle_record_create, NULL,
2197 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2198 {&handle_record_remove, NULL,
2199 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2200 {&handle_zone_to_name, NULL,
2201 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, sizeof (struct ZoneToNameMessage) },
2202 {&handle_iteration_start, NULL,
2203 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage) },
2204 {&handle_iteration_next, NULL,
2205 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, sizeof (struct ZoneIterationNextMessage) },
2206 {&handle_iteration_stop, NULL,
2207 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage) },
2211 unsigned int counter;
2213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2216 /* Load private keys from disk */
2218 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore",
2219 "zonefile_directory",
2220 &zonefile_directory))
2222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2223 _("No directory to load zonefiles specified in configuration\n"));
2224 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2228 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2230 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2232 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2233 _("Creating directory `%s' for zone files failed!\n"),
2234 zonefile_directory);
2235 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2239 "Created directory `%s' for zone files\n",
2240 zonefile_directory);
2243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2244 "Scanning directory `%s' for zone files\n", zonefile_directory);
2245 zonekeys = GNUNET_CONTAINER_multihashmap_create (16);
2247 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2249 "Found %u zone files\n",
2252 /* Loading database plugin */
2254 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2256 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2258 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2259 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2260 GNUNET_free (database);
2261 if (NULL == GSN_database)
2263 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2264 "Could not load database backend `%s'\n",
2266 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2270 /* Configuring server handles */
2271 GNUNET_SERVER_add_handlers (server, handlers);
2272 snc = GNUNET_SERVER_notification_context_create (server, 16);
2273 GNUNET_SERVER_disconnect_notify (server,
2274 &client_disconnect_notification,
2276 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2282 * The main function for the template service.
2284 * @param argc number of arguments from the command line
2285 * @param argv command line arguments
2286 * @return 0 ok, 1 on error
2289 main (int argc, char *const *argv)
2291 return (GNUNET_OK ==
2292 GNUNET_SERVICE_run (argc, argv, "namestore",
2293 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2296 /* end of gnunet-service-namestore.c */