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_getopt_lib.h"
28 #include "gnunet_service_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 * Returns the expiration time of the given block of records. The block
301 * expiration time is the expiration time of the block with smallest
304 * @param rd_count number of records given in 'rd'
305 * @param rd array of records
306 * @return absolute expiration time
308 static struct GNUNET_TIME_Absolute
309 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
312 struct GNUNET_TIME_Absolute expire;
313 struct GNUNET_TIME_Absolute at;
314 struct GNUNET_TIME_Relative rt;
317 return GNUNET_TIME_UNIT_ZERO_ABS;
318 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
319 for (c = 0; c < rd_count; c++)
321 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
323 rt.rel_value = rd[c].expiration_time;
324 at = GNUNET_TIME_relative_to_absolute (rt);
328 at.abs_value = rd[c].expiration_time;
330 expire = GNUNET_TIME_absolute_min (at, expire);
337 * Task run during shutdown.
343 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
345 struct GNUNET_NAMESTORE_ZoneIteration *no;
346 struct GNUNET_NAMESTORE_Client *nc;
348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
351 GNUNET_SERVER_notification_context_destroy (snc);
354 GNUNET_CONTAINER_multihashmap_iterate (zonekeys, &zone_to_disk_it, NULL);
355 GNUNET_CONTAINER_multihashmap_destroy (zonekeys);
357 while (NULL != (nc = client_head))
359 while (NULL != (no = nc->op_head))
361 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
364 GNUNET_SERVER_client_drop(nc->client);
365 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
368 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
369 GNUNET_free (db_lib_name);
371 GNUNET_free_non_null (zonefile_directory);
372 zonefile_directory = NULL;
377 * Lookup our internal data structure for a given client.
379 * @param client server client handle to use for the lookup
380 * @return our internal structure for the client, NULL if
381 * we do not have any yet
383 static struct GNUNET_NAMESTORE_Client *
384 client_lookup (struct GNUNET_SERVER_Client *client)
386 struct GNUNET_NAMESTORE_Client *nc;
388 GNUNET_assert (NULL != client);
389 for (nc = client_head; NULL != nc; nc = nc->next)
390 if (client == nc->client)
397 * Called whenever a client is disconnected.
398 * Frees our resources associated with that client.
401 * @param client identification of the client
404 client_disconnect_notification (void *cls,
405 struct GNUNET_SERVER_Client *client)
407 struct GNUNET_NAMESTORE_ZoneIteration *no;
408 struct GNUNET_NAMESTORE_Client *nc;
412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
413 "Client %p disconnected\n",
415 nc = client_lookup (client);
418 while (NULL != (no = nc->op_head))
420 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
423 GNUNET_SERVER_client_drop (nc->client);
424 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
430 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
433 * @param client GNUNET_SERVER_Client sending the message
434 * @param message unused
437 handle_start (void *cls,
438 struct GNUNET_SERVER_Client *client,
439 const struct GNUNET_MessageHeader *message)
441 struct GNUNET_NAMESTORE_Client *nc;
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
444 "Client %p connected\n", client);
445 if (NULL != client_lookup (client))
448 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
451 nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
453 GNUNET_SERVER_notification_context_add (snc, client);
454 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc);
455 GNUNET_SERVER_client_keep (client);
456 GNUNET_SERVER_receive_done (client, GNUNET_OK);
461 * Context for name lookups passed from 'handle_lookup_name' to
462 * 'handle_lookup_name_it' as closure
464 struct LookupNameContext
467 * The client to send the response to
469 struct GNUNET_NAMESTORE_Client *nc;
474 const struct GNUNET_CRYPTO_ShortHashCode *zone;
482 * Operation id for the name lookup
487 * Requested specific record type
489 uint32_t record_type;
494 * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
496 * @param cls a 'struct LookupNameContext *' with information about the request
497 * @param zone_key zone key of the zone
498 * @param expire expiration time
500 * @param rd_count number of records
501 * @param rd array of records
502 * @param signature signature
505 handle_lookup_name_it (void *cls,
506 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
507 struct GNUNET_TIME_Absolute expire,
509 unsigned int rd_count,
510 const struct GNUNET_NAMESTORE_RecordData *rd,
511 const struct GNUNET_CRYPTO_RsaSignature *signature)
513 struct LookupNameContext *lnc = cls;
514 struct LookupNameResponseMessage *lnr_msg;
515 struct GNUNET_NAMESTORE_RecordData *rd_selected;
516 struct GNUNET_NAMESTORE_CryptoContainer *cc;
517 struct GNUNET_CRYPTO_RsaSignature *signature_new;
518 struct GNUNET_TIME_Absolute e;
519 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
520 struct GNUNET_HashCode long_hash;
527 int contains_signature;
531 name_len = (NULL == name) ? 0 : strlen(name) + 1;
534 /* count records to copy */
535 if (0 != lnc->record_type)
537 /* special record type needed */
538 for (c = 0; c < rd_count; c++)
539 if (rd[c].record_type == lnc->record_type)
540 copied_elements++; /* found matching record */
541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
542 "Found %u records with type %u for name `%s' in zone `%s'\n",
546 GNUNET_short_h2s(lnc->zone));
547 if (copied_elements > 0)
549 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
551 for (c = 0; c < rd_count; c++)
553 if (rd[c].record_type == lnc->record_type)
555 /* found matching record */
556 rd_selected[copied_elements] = rd[c]; /* shallow copy! */
564 copied_elements = rd_count;
565 rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
567 // FIXME: need to adjust 'rd' from relative to absolute times!
568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
569 "Found %u records for name `%s' in zone `%s'\n",
572 GNUNET_short_h2s (lnc->zone));
574 if ((copied_elements == rd_count) && (NULL != signature))
575 contains_signature = GNUNET_YES; /* returning all records, so include signature */
577 contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
579 authoritative = GNUNET_NO;
580 signature_new = NULL;
581 if ((NULL != zone_key) && (copied_elements == rd_count))
583 GNUNET_CRYPTO_short_hash (zone_key,
584 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
586 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
587 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash)))
589 e = get_block_expiration_time (rd_count, rd);
590 signature_new = GNUNET_NAMESTORE_create_signature (cc->privkey, e, name, rd, rd_count);
591 GNUNET_assert (NULL != signature_new);
592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
593 "Creating signature for name `%s' with %u records in zone `%s'\n",
596 GNUNET_short_h2s(&zone_key_hash));
597 authoritative = GNUNET_YES;
601 rd_ser_len = GNUNET_NAMESTORE_records_get_size (copied_elements, rd_selected);
602 r_size = sizeof (struct LookupNameResponseMessage) +
603 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
607 "Sending `%s' message\n",
608 "NAMESTORE_LOOKUP_NAME_RESPONSE");
609 lnr_msg = GNUNET_malloc (r_size);
610 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
611 lnr_msg->gns_header.header.size = ntohs (r_size);
612 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
613 lnr_msg->rd_count = htons (copied_elements);
614 lnr_msg->rd_len = htons (rd_ser_len);
615 lnr_msg->name_len = htons (name_len);
616 lnr_msg->expire = GNUNET_TIME_absolute_hton (get_block_expiration_time (copied_elements,
618 name_tmp = (char *) &lnr_msg[1];
619 memcpy (name_tmp, name, name_len);
620 rd_tmp = &name_tmp[name_len];
621 GNUNET_NAMESTORE_records_serialize (copied_elements, rd_selected, rd_ser_len, rd_tmp);
623 if (rd_selected != rd)
624 GNUNET_free_non_null (rd_selected);
626 if (NULL != zone_key)
627 lnr_msg->public_key = *zone_key;
628 if (GNUNET_YES == authoritative)
630 /* use new created signature */
631 lnr_msg->contains_sig = htons (GNUNET_YES);
632 GNUNET_assert (NULL != signature_new);
633 lnr_msg->signature = *signature_new;
634 GNUNET_free (signature_new);
636 else if (GNUNET_YES == contains_signature)
638 /* use existing signature */
639 lnr_msg->contains_sig = htons (GNUNET_YES);
640 GNUNET_assert (NULL != signature);
641 lnr_msg->signature = *signature;
643 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client,
644 &lnr_msg->gns_header.header,
646 GNUNET_free (lnr_msg);
651 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
654 * @param client GNUNET_SERVER_Client sending the message
655 * @param message message of type 'struct LookupNameMessage'
658 handle_lookup_name (void *cls,
659 struct GNUNET_SERVER_Client *client,
660 const struct GNUNET_MessageHeader *message)
662 const struct LookupNameMessage *ln_msg;
663 struct LookupNameContext lnc;
664 struct GNUNET_NAMESTORE_Client *nc;
670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671 "Received `%s' message\n",
672 "NAMESTORE_LOOKUP_NAME");
673 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
676 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
679 if (NULL == (nc = client_lookup(client)))
682 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
685 ln_msg = (const struct LookupNameMessage *) message;
686 rid = ntohl (ln_msg->gns_header.r_id);
687 name_len = ntohl (ln_msg->name_len);
688 type = ntohl (ln_msg->record_type);
689 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
692 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
695 name = (const char *) &ln_msg[1];
696 if (name[name_len -1] != '\0')
699 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
702 if (GNUNET_NAMESTORE_TYPE_ANY == type)
703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
704 "Looking up all records for name `%s' in zone `%s'\n",
706 GNUNET_short_h2s(&ln_msg->zone));
708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
709 "Looking up records with type %u for name `%s' in zone `%s'\n",
711 GNUNET_short_h2s(&ln_msg->zone));
713 /* do the actual lookup */
714 lnc.request_id = rid;
716 lnc.record_type = type;
718 lnc.zone = &ln_msg->zone;
720 GSN_database->iterate_records (GSN_database->cls,
721 &ln_msg->zone, name, 0 /* offset */,
722 &handle_lookup_name_it, &lnc))
724 /* internal error (in database plugin); might be best to just hang up on
725 plugin rather than to signal that there are 'no' results, which
726 might also be false... */
728 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
731 GNUNET_SERVER_receive_done (client, GNUNET_OK);
736 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
739 * @param client GNUNET_SERVER_Client sending the message
740 * @param message message of type 'struct RecordPutMessage'
743 handle_record_put (void *cls,
744 struct GNUNET_SERVER_Client *client,
745 const struct GNUNET_MessageHeader *message)
747 struct GNUNET_NAMESTORE_Client *nc;
748 const struct RecordPutMessage *rp_msg;
749 struct GNUNET_TIME_Absolute expire;
750 const struct GNUNET_CRYPTO_RsaSignature *signature;
751 struct RecordPutResponseMessage rpr_msg;
752 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
764 "Received `%s' message\n",
765 "NAMESTORE_RECORD_PUT");
766 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
769 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
772 if (NULL == (nc = client_lookup (client)))
775 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
778 rp_msg = (const struct RecordPutMessage *) message;
779 rid = ntohl (rp_msg->gns_header.r_id);
780 msg_size = ntohs (rp_msg->gns_header.header.size);
781 name_len = ntohs (rp_msg->name_len);
782 rd_count = ntohs (rp_msg->rd_count);
783 rd_ser_len = ntohs (rp_msg->rd_len);
784 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >= MAX_NAME_LEN) || (0 == name_len))
787 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
790 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
791 if (msg_size != msg_size_exp)
794 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
797 name = (const char *) &rp_msg[1];
798 if ('\0' != name[name_len -1])
801 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
804 expire = GNUNET_TIME_absolute_ntoh (rp_msg->expire);
805 signature = &rp_msg->signature;
806 rd_ser = &name[name_len];
808 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
811 GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd))
814 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
817 GNUNET_CRYPTO_short_hash (&rp_msg->public_key,
818 sizeof (rp_msg->public_key),
820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
821 "Putting %u records under name `%s' in zone `%s'\n",
823 GNUNET_short_h2s (&zone_hash));
824 res = GSN_database->put_records(GSN_database->cls,
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "Putting record for name `%s': %s\n",
833 (res == GNUNET_OK) ? "OK" : "FAILED");
835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
836 "Sending `%s' message\n",
837 "RECORD_PUT_RESPONSE");
838 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
839 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
840 rpr_msg.gns_header.r_id = htonl (rid);
841 rpr_msg.op_result = htonl (res);
842 GNUNET_SERVER_notification_context_unicast (snc,
844 &rpr_msg.gns_header.header,
846 GNUNET_SERVER_receive_done (client, GNUNET_OK);
850 /////////////////////////////////////////////////////////////
854 * Context for record create operations passed from 'handle_record_create' to
855 * 'handle_create_record_it' as closure
857 struct CreateRecordContext
862 const struct GNUNET_NAMESTORE_RecordData *rd;
867 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
872 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
875 * Name for the record to create
880 * Record expiration time
882 struct GNUNET_TIME_Absolute expire;
885 * result returned from 'handle_create_record_it'
886 * GNUNET_SYSERR: failed to create the record
887 * GNUNET_NO: we updated an existing record or identical entry existed
888 * GNUNET_YES : we created a new record
895 * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
896 * in handle_record_create
898 * @param cls a 'struct CreateRecordContext *' with information about the request
899 * @param pubkey zone key of the zone
900 * @param expire expiration time
902 * @param rd_count number of records
903 * @param rd array of records
904 * @param signature signature
907 handle_create_record_it (void *cls,
908 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
909 struct GNUNET_TIME_Absolute expire,
911 unsigned int rd_count,
912 const struct GNUNET_NAMESTORE_RecordData *rd,
913 const struct GNUNET_CRYPTO_RsaSignature *signature)
915 struct CreateRecordContext *crc = cls;
916 struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
917 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
918 struct GNUNET_TIME_Absolute block_expiration;
920 int exist = GNUNET_SYSERR;
921 int update = GNUNET_NO;
923 int rd_count_new = 0;
925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
926 "Found %u existing records for `%s'\n",
927 rd_count, crc->name);
928 for (c = 0; c < rd_count; c++)
930 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) &&
931 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
933 /* Update unique PKEY */
938 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) &&
939 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
941 /* Update unique PSEU */
946 if ((crc->rd->record_type == rd[c].record_type) &&
947 (crc->rd->data_size == rd[c].data_size) &&
948 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
951 "Found existing records for `%s' to update expiration date!\n",
954 if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
955 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
956 == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
962 if (exist == GNUNET_SYSERR)
964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
965 "No existing record for name `%s'!\n",
967 rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
968 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
969 rd_count_new = rd_count + 1;
970 rd_new[rd_count] = *(crc->rd);
972 else if (update == GNUNET_NO)
974 /* Exact same record already exists */
975 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
976 "Matching record for %s' exists, no change required!\n",
978 crc->res = GNUNET_NO;
984 GNUNET_assert (GNUNET_YES == update);
985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
986 "Updating existing records for `%s'!\n",
988 rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
989 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
990 rd_count_new = rd_count;
991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
992 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
993 ? "Updating absolute expiration from %llu to %llu!\n"
994 : "Updating relative expiration from %llu to %llu!\n",
995 rd_new[exist].expiration_time, crc->rd->expiration_time);
996 rd_new[exist] = *(crc->rd);
999 block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
1000 if (block_expiration.abs_value != expire.abs_value)
1001 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1002 "Updated block expiration time\n");
1004 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1006 /* Database operation */
1007 GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
1008 res = GSN_database->put_records(GSN_database->cls,
1009 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
1012 rd_count_new, rd_new,
1014 GNUNET_break (GNUNET_OK == res);
1015 if (res == GNUNET_OK)
1016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
1018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
1021 GNUNET_free_non_null (rd_new);
1025 /* failed to create the record */
1026 crc->res = GNUNET_SYSERR;
1029 /* database operations OK */
1030 if (GNUNET_YES == update)
1032 /* we updated an existing record */
1033 crc->res = GNUNET_NO;
1037 /* we created a new record */
1038 crc->res = GNUNET_YES;
1042 /* identical entry existed, so we did nothing */
1043 crc->res = GNUNET_NO;
1048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
1053 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1056 * @param client GNUNET_SERVER_Client sending the message
1057 * @param message message of type 'struct RecordCreateMessage'
1060 handle_record_create (void *cls,
1061 struct GNUNET_SERVER_Client *client,
1062 const struct GNUNET_MessageHeader *message)
1064 struct GNUNET_NAMESTORE_Client *nc;
1065 const struct RecordCreateMessage *rp_msg;
1066 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1067 struct CreateRecordContext crc;
1068 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1069 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1070 struct RecordCreateResponseMessage rcr_msg;
1071 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1072 struct GNUNET_HashCode long_hash;
1075 size_t msg_size_exp;
1079 const char *pkey_tmp;
1080 const char *name_tmp;
1082 unsigned int rd_count;
1084 struct GNUNET_NAMESTORE_RecordData rd;
1086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1087 "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1088 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1091 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1094 if (NULL == (nc = client_lookup (client)))
1097 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1100 rp_msg = (const struct RecordCreateMessage *) message;
1101 rid = ntohl (rp_msg->gns_header.r_id);
1102 name_len = ntohs (rp_msg->name_len);
1103 msg_size = ntohs (message->size);
1104 rd_count = ntohs (rp_msg->rd_count);
1105 rd_ser_len = ntohs (rp_msg->rd_len);
1106 key_len = ntohs (rp_msg->pkey_len);
1107 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1108 if ( (msg_size != msg_size_exp) || (1 != rd_count) )
1111 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1114 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1117 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1120 pkey_tmp = (const char *) &rp_msg[1];
1121 name_tmp = &pkey_tmp[key_len];
1122 rd_ser = &name_tmp[name_len];
1123 if (name_tmp[name_len -1] != '\0')
1126 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1129 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1132 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1136 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, 1, &rd))
1139 GNUNET_CRYPTO_rsa_key_free (pkey);
1140 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1143 /* Extracting and converting private key */
1144 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
1145 GNUNET_CRYPTO_short_hash (&pub,
1146 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1148 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1150 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1153 "Received new private key for zone `%s'\n",
1154 GNUNET_short_h2s(&pubkey_hash));
1155 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1156 cc->privkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len);
1157 cc->zone = pubkey_hash;
1158 GNUNET_assert (GNUNET_YES ==
1159 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc,
1160 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1164 "Creating record for name `%s' in zone `%s'\n",
1165 name_tmp, GNUNET_short_h2s(&pubkey_hash));
1166 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1167 crc.res = GNUNET_SYSERR;
1171 crc.name = name_tmp;
1173 /* Get existing records for name */
1174 res = GSN_database->iterate_records (GSN_database->cls, &pubkey_hash, name_tmp, 0,
1175 &handle_create_record_it, &crc);
1176 if (res != GNUNET_SYSERR)
1178 GNUNET_CRYPTO_rsa_key_free (pkey);
1181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1182 "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1183 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1184 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1185 rcr_msg.gns_header.r_id = htonl (rid);
1186 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1187 rcr_msg.op_result = htonl (GNUNET_YES);
1188 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1189 rcr_msg.op_result = htonl (GNUNET_NO);
1191 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1192 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
1193 &rcr_msg.gns_header.header,
1195 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1200 * RemoveRecordContext
1202 * Context for record remove operations passed from 'handle_record_remove' to
1203 * 'handle_record_remove_it' as closure
1205 struct RemoveRecordContext
1210 struct GNUNET_NAMESTORE_RecordData *rd;
1213 * Zone's private keys
1215 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1224 * 1 : Could not find record to remove, empty result set
1225 * 2 : Could not find record to remove, record did not exist in result set
1226 * 3 : Could not remove records from database
1227 * 4 : Could not put records into database
1237 handle_record_remove_it (void *cls,
1238 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1239 struct GNUNET_TIME_Absolute expire,
1241 unsigned int rd_count,
1242 const struct GNUNET_NAMESTORE_RecordData *rd,
1243 const struct GNUNET_CRYPTO_RsaSignature *signature)
1245 static struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1246 struct RemoveRecordContext *rrc = cls;
1249 unsigned int rd_count_new;
1251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1252 "Name `%s 'currently has %u records\n",
1256 /* Could not find record to remove */
1261 /* Find record to remove */
1262 found = GNUNET_SYSERR;
1263 for (c = 0; c < rd_count; c++)
1266 if (rd[c].flags != rrc->rd->flags)
1268 if (rd[c].record_type != rrc->rd->record_type)
1271 if (rd[c].data_size != rrc->rd->data_size)
1274 if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1281 if (GNUNET_SYSERR == found)
1283 /* Could not find record to remove */
1290 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1293 "No records left for name `%s', removing name\n",
1295 GNUNET_CRYPTO_short_hash (zone_key,
1296 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1299 GSN_database->remove_records (GSN_database->cls,
1303 /* Could not remove records from database */
1311 rd_count_new = rd_count - 1;
1312 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1313 unsigned int c2 = 0;
1314 for (c = 0; c < rd_count; c++)
1318 GNUNET_assert (c2 < rd_count_new);
1324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1326 GSN_database->put_records(GSN_database->cls,
1330 rd_count_new, rd_new,
1333 /* Could not put records into database */
1342 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1345 * @param client GNUNET_SERVER_Client sending the message
1346 * @param message message of type 'struct RecordRemoveMessage'
1349 handle_record_remove (void *cls,
1350 struct GNUNET_SERVER_Client *client,
1351 const struct GNUNET_MessageHeader *message)
1353 struct GNUNET_NAMESTORE_Client *nc;
1354 const struct RecordRemoveMessage *rr_msg;
1355 struct RecordRemoveResponseMessage rrr_msg;
1356 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1357 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1358 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1359 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1360 struct GNUNET_HashCode long_hash;
1361 const char *pkey_tmp;
1362 const char *name_tmp;
1368 size_t msg_size_exp = 0;
1372 int res = GNUNET_SYSERR;
1374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1375 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1378 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1381 if (NULL == (nc = client_lookup(client)))
1384 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1387 rr_msg = (const struct RecordRemoveMessage *) message;
1388 rid = ntohl (rr_msg->gns_header.r_id);
1389 name_len = ntohs (rr_msg->name_len);
1390 rd_ser_len = ntohs (rr_msg->rd_len);
1391 rd_count = ntohs (rr_msg->rd_count);
1392 key_len = ntohs (rr_msg->pkey_len);
1393 msg_size = ntohs (message->size);
1395 if ((name_len >=MAX_NAME_LEN) || (0 == name_len))
1398 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1401 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1402 if (msg_size != msg_size_exp)
1405 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1408 pkey_tmp = (const char *) &rr_msg[1];
1409 name_tmp = &pkey_tmp[key_len];
1410 rd_ser = &name_tmp[name_len];
1411 if ('\0' != name_tmp[name_len -1])
1414 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1417 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1420 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1423 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
1424 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1425 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1427 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (zonekeys, &long_hash))
1429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1430 "Received new private key for zone `%s'\n",
1431 GNUNET_short_h2s(&pubkey_hash));
1432 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1433 cc->privkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len);
1434 cc->zone = pubkey_hash;
1435 GNUNET_assert (GNUNET_YES ==
1436 GNUNET_CONTAINER_multihashmap_put (zonekeys,
1438 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1442 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1443 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1444 if ((res != GNUNET_OK) || (rd_count > 1))
1446 GNUNET_break_op (0);
1452 /* remove the whole name and all records */
1453 /* Database operation */
1454 res = GSN_database->remove_records (GSN_database->cls,
1457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1458 name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1460 if (GNUNET_OK != res)
1461 /* Could not remove entry from database */
1468 /* remove a single record */
1469 struct RemoveRecordContext rrc;
1473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1475 /* Database operation */
1476 res = GSN_database->iterate_records (GSN_database->cls,
1480 handle_record_remove_it, &rrc);
1482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1483 name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1489 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1490 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1491 rrr_msg.gns_header.r_id = htonl (rid);
1492 rrr_msg.op_result = htonl (res);
1493 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1495 GNUNET_CRYPTO_rsa_key_free (pkey);
1497 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1503 * Context for record remove operations passed from 'handle_zone_to_name' to
1504 * 'handle_zone_to_name_it' as closure
1506 struct ZoneToNameCtx
1511 struct GNUNET_NAMESTORE_Client *nc;
1521 * Zone to name iterator
1523 * @param cls struct ZoneToNameCtx *
1524 * @param zone_key the zone key
1525 * @param expire expiration date
1527 * @param rd_count number of records
1528 * @param rd record data
1529 * @param signature signature
1532 handle_zone_to_name_it (void *cls,
1533 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1534 struct GNUNET_TIME_Absolute expire,
1536 unsigned int rd_count,
1537 const struct GNUNET_NAMESTORE_RecordData *rd,
1538 const struct GNUNET_CRYPTO_RsaSignature *signature)
1540 struct ZoneToNameCtx *ztn_ctx = cls;
1541 struct ZoneToNameResponseMessage *ztnr_msg;
1542 int16_t res = GNUNET_SYSERR;
1543 uint16_t name_len = 0;
1544 uint16_t rd_ser_len = 0 ;
1545 int32_t contains_sig = 0;
1546 size_t msg_size = 0;
1548 char *rd_ser = NULL;
1553 if ((zone_key != NULL) && (name != NULL))
1556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1558 name_len = strlen (name) +1;
1562 /* no result found */
1563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1570 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1571 rd_ser = GNUNET_malloc (rd_ser_len);
1572 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1577 if (signature != NULL)
1578 contains_sig = GNUNET_YES;
1580 contains_sig = GNUNET_NO;
1582 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1583 ztnr_msg = GNUNET_malloc (msg_size);
1585 name_tmp = (char *) &ztnr_msg[1];
1586 rd_tmp = &name_tmp[name_len];
1587 sig_tmp = &rd_tmp[rd_ser_len];
1589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1590 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1591 ztnr_msg->gns_header.header.size = htons (msg_size);
1592 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1593 ztnr_msg->res = htons (res);
1594 ztnr_msg->rd_len = htons (rd_ser_len);
1595 ztnr_msg->rd_count = htons (rd_count);
1596 ztnr_msg->name_len = htons (name_len);
1597 ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1598 if (zone_key != NULL)
1599 ztnr_msg->zone_key = *zone_key;
1601 memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1603 if ((name_len > 0) && (name != NULL))
1604 memcpy (name_tmp, name, name_len);
1606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name is `%s', has %u records, rd ser len %u msg_size %u\n", name, rd_count, rd_ser_len, msg_size);
1607 if ((rd_ser_len > 0) && (rd_ser != NULL))
1608 memcpy (rd_tmp, rd_ser, rd_ser_len);
1609 if ((GNUNET_YES == contains_sig) && (signature != NULL))
1610 memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1612 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1613 GNUNET_free (ztnr_msg);
1614 GNUNET_free_non_null (rd_ser);
1619 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1622 * @param client GNUNET_SERVER_Client sending the message
1623 * @param message message of type 'struct ZoneToNameMessage'
1626 handle_zone_to_name (void *cls,
1627 struct GNUNET_SERVER_Client *client,
1628 const struct GNUNET_MessageHeader *message)
1630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1631 struct GNUNET_NAMESTORE_Client *nc;
1632 struct ZoneToNameMessage *ztn_msg;
1633 struct ZoneToNameCtx ztn_ctx;
1634 size_t msg_size = 0;
1637 if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1639 GNUNET_break_op (0);
1640 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1644 nc = client_lookup(client);
1647 GNUNET_break_op (0);
1648 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1652 ztn_msg = (struct ZoneToNameMessage *) message;
1654 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1656 GNUNET_break_op (0);
1657 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1661 rid = ntohl (ztn_msg->gns_header.r_id);
1666 struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1667 GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1670 GNUNET_short_h2s (&ztn_msg->value_zone));
1672 GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1674 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1679 * Copy record, data has to be free'd separetely
1681 * @param src source record
1682 * @param dest destination record
1685 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1687 memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1688 dest->data = GNUNET_malloc (src->data_size);
1689 memcpy ((void *) dest->data, src->data, src->data_size);
1694 * ZoneIterationProcResult
1696 * Context for record remove operations passed from
1697 * 'find_next_zone_iteration_result' to 'zone_iteraterate_proc' as closure
1699 struct ZoneIterationProcResult
1702 * The zone iteration handle
1704 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1707 * Iteration result: iteration done?
1709 int res_iteration_finished;
1712 * Iteration result: number of records included
1714 int records_included;
1717 * Iteration result: is a valid signature included?
1729 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1734 struct GNUNET_NAMESTORE_RecordData *rd;
1739 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1744 struct GNUNET_CRYPTO_RsaSignature signature;
1749 struct GNUNET_TIME_Absolute expire;
1754 * Process results for zone iteration from database
1756 * @param cls struct ZoneIterationProcResult *proc
1757 * @param zone_key the zone key
1758 * @param expire expiration time
1760 * @param rd_count number of records for this name
1761 * @param rd record data
1762 * @param signature block signature
1765 zone_iteraterate_proc (void *cls,
1766 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1767 struct GNUNET_TIME_Absolute expire,
1769 unsigned int rd_count,
1770 const struct GNUNET_NAMESTORE_RecordData *rd,
1771 const struct GNUNET_CRYPTO_RsaSignature *signature)
1773 struct ZoneIterationProcResult *proc = cls;
1774 struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1775 struct GNUNET_CRYPTO_RsaSignature *new_signature;
1776 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1777 struct GNUNET_CRYPTO_ShortHashCode hash;
1778 struct GNUNET_HashCode long_hash;
1779 struct GNUNET_TIME_Absolute e;
1780 unsigned int rd_count_filtered = 0;
1784 proc->res_iteration_finished = GNUNET_NO;
1785 proc->records_included = 0;
1787 if ((zone_key == NULL) && (name == NULL))
1789 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1790 proc->res_iteration_finished = GNUNET_YES;
1794 else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1796 rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1797 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1798 for (c = 0; c < rd_count; c++)
1800 include = GNUNET_YES;
1801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1802 c, rd[c].flags, proc->zi->must_have_flags);
1803 /* Checking must have flags */
1804 if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1812 include = GNUNET_NO;
1815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1816 c, rd[c].flags, proc->zi->must_not_have_flags);
1817 if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1820 include = GNUNET_NO;
1825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1827 if (GNUNET_YES == include)
1829 copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1830 rd_count_filtered++;
1834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1836 proc->records_included = rd_count_filtered;
1837 if (0 == rd_count_filtered)
1839 GNUNET_free (rd_filtered);
1842 proc->rd = rd_filtered;
1843 proc->name = GNUNET_strdup(name);
1844 memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1847 proc->has_signature = GNUNET_NO;
1848 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1849 GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1850 proc->zone_hash = hash;
1852 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1854 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1855 e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1857 new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1858 GNUNET_assert (signature != NULL);
1859 proc->signature = (*new_signature);
1860 GNUNET_free (new_signature);
1861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1862 name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1863 proc->has_signature = GNUNET_YES;
1865 else if (rd_count_filtered == rd_count)
1867 proc->expire = expire;
1868 if (NULL != signature)
1870 proc->signature = (*signature);
1871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1872 name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1873 proc->has_signature = GNUNET_YES;
1877 memset (&proc->signature, '\0', sizeof (proc->signature));
1878 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1888 /////////////////////////////////////////////////////////////
1892 * Find next zone iteration result in database
1894 * @param proc the zone iteration processing to use
1897 find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1899 struct GNUNET_CRYPTO_ShortHashCode *zone;
1901 if (GNUNET_YES == proc->zi->has_zone)
1902 zone = &proc->zi->zone;
1907 if (GNUNET_SYSERR ==
1908 GSN_database->iterate_records (GSN_database->cls, zone, NULL,
1910 &zone_iteraterate_proc, proc))
1917 while ((0 == proc->records_included) && (GNUNET_NO == proc->res_iteration_finished));
1922 * Send zone iteration result to client
1924 * @param proc the zone iteration processing result to send
1927 send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1929 struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1930 struct ZoneIterationResponseMessage zir_end;
1931 struct ZoneIterationResponseMessage *zir_msg;
1938 if (GNUNET_YES == proc->res_iteration_finished)
1940 if (zi->has_zone == GNUNET_YES)
1941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1942 "No more results for zone `%s'\n",
1943 GNUNET_short_h2s(&zi->zone));
1945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1946 "No more results for all zones\n");
1947 memset (&zir_end, 0, sizeof (zir_end));
1948 zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1949 zir_end.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1950 zir_end.gns_header.r_id = htonl(zi->request_id);
1951 GNUNET_SERVER_notification_context_unicast (snc,
1953 &zir_end.gns_header.header, GNUNET_NO);
1954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1955 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1959 GNUNET_assert (proc->records_included > 0);
1960 if (GNUNET_YES == zi->has_zone)
1961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1962 "Sending name `%s' for iteration over zone `%s'\n",
1963 proc->name, GNUNET_short_h2s(&zi->zone));
1965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1966 "Sending name `%s' for iteration over all zones\n",
1968 name_len = strlen (proc->name) + 1;
1969 rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);
1970 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1972 zir_msg = GNUNET_malloc(msg_size);
1973 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1974 zir_msg->gns_header.header.size = htons (msg_size);
1975 zir_msg->gns_header.r_id = htonl(zi->request_id);
1976 zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire);
1977 zir_msg->reserved = htons (0);
1978 zir_msg->name_len = htons (name_len);
1979 zir_msg->rd_count = htons (proc->records_included);
1980 zir_msg->rd_len = htons (rd_ser_len);
1981 zir_msg->signature = proc->signature;
1982 zir_msg->public_key = proc->zone_key;
1983 name_tmp = (char *) &zir_msg[1];
1984 memcpy (name_tmp, proc->name, name_len);
1985 rd_ser = &name_tmp[name_len];
1986 GNUNET_NAMESTORE_records_serialize (proc->records_included, proc->rd, rd_ser_len, rd_ser);
1987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1988 "Sending `%s' message with size %u\n",
1989 "ZONE_ITERATION_RESPONSE",
1991 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client,
1992 (const struct GNUNET_MessageHeader *) zir_msg,
1994 GNUNET_free (zir_msg);
1999 * Clean up after zone iteration
2000 * @param proc the zone iteration processor
2003 clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
2007 GNUNET_free_non_null (proc->name);
2009 for (c = 0; c < proc->records_included; c++)
2010 GNUNET_free ((void *) proc->rd[c].data);
2011 GNUNET_free_non_null (proc->rd);
2013 proc->records_included = 0;
2018 * Perform the next round of the zone iteration.
2020 * @param zi zone iterator to process
2023 run_zone_iteration_round (struct GNUNET_NAMESTORE_ZoneIteration *zi)
2025 struct ZoneIterationProcResult proc;
2027 memset (&proc, 0, sizeof (proc));
2029 find_next_zone_iteration_result (&proc);
2030 if (GNUNET_YES == proc.res_iteration_finished)
2032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2033 "Zone iteration done\n");
2035 else if (0 != proc.records_included)
2037 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2038 "Zone iteration returns %u records\n",
2039 proc.records_included);
2041 send_zone_iteration_result (&proc);
2042 clean_up_zone_iteration_result (&proc);
2047 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
2050 * @param client GNUNET_SERVER_Client sending the message
2051 * @param message message of type 'struct ZoneIterationStartMessage'
2054 handle_iteration_start (void *cls,
2055 struct GNUNET_SERVER_Client *client,
2056 const struct GNUNET_MessageHeader *message)
2058 static struct GNUNET_CRYPTO_ShortHashCode zeros;
2059 const struct ZoneIterationStartMessage *zis_msg;
2060 struct GNUNET_NAMESTORE_Client *nc;
2061 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2064 nc = client_lookup (client);
2067 GNUNET_break_op (0);
2068 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2071 zis_msg = (const struct ZoneIterationStartMessage *) message;
2072 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2073 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2076 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2077 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2078 if (0 == memcmp (&zeros, &zis_msg->zone, sizeof (zeros)))
2080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2081 zi->zone = zis_msg->zone;
2082 zi->has_zone = GNUNET_NO;
2086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2087 "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2088 zi->zone = zis_msg->zone;
2089 zi->has_zone = GNUNET_YES;
2091 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2092 run_zone_iteration_round (zi);
2093 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2098 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2101 * @param client GNUNET_SERVER_Client sending the message
2102 * @param message message of type 'struct ZoneIterationStopMessage'
2105 handle_iteration_stop (void *cls,
2106 struct GNUNET_SERVER_Client *client,
2107 const struct GNUNET_MessageHeader *message)
2109 struct GNUNET_NAMESTORE_Client *nc;
2110 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2111 const struct ZoneIterationStopMessage *zis_msg;
2114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2115 "Received `%s' message\n",
2116 "ZONE_ITERATION_STOP");
2117 nc = client_lookup(client);
2121 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2124 zis_msg = (const struct ZoneIterationStopMessage *) message;
2125 rid = ntohl (zis_msg->gns_header.r_id);
2126 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2127 if (zi->request_id == rid)
2132 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2135 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2136 if (GNUNET_YES == zi->has_zone)
2137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2138 "Stopped zone iteration for zone `%s'\n",
2139 GNUNET_short_h2s (&zi->zone));
2141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2142 "Stopped zone iteration over all zones\n");
2144 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2149 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT' message
2152 * @param client GNUNET_SERVER_Client sending the message
2153 * @param message message of type 'struct ZoneIterationNextMessage'
2156 handle_iteration_next (void *cls,
2157 struct GNUNET_SERVER_Client *client,
2158 const struct GNUNET_MessageHeader *message)
2160 struct GNUNET_NAMESTORE_Client *nc;
2161 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2162 const struct ZoneIterationNextMessage *zis_msg;
2165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2166 nc = client_lookup(client);
2170 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2173 zis_msg = (const struct ZoneIterationNextMessage *) message;
2174 rid = ntohl (zis_msg->gns_header.r_id);
2175 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2176 if (zi->request_id == rid)
2181 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2184 run_zone_iteration_round (zi);
2185 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2190 * Load zone keys from directory by reading all .zkey files in this directory
2192 * @param cls int * 'counter' to store the number of files found
2193 * @param filename directory to scan
2194 * @return GNUNET_OK to continue
2197 zonekey_file_it (void *cls, const char *filename)
2199 unsigned int *counter = cls;
2200 struct GNUNET_HashCode long_hash;
2201 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2202 struct GNUNET_NAMESTORE_CryptoContainer *c;
2203 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
2205 if ((NULL == filename) ||
2206 (NULL == strstr(filename, ".zkey")))
2208 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
2209 if (NULL == privkey)
2211 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2212 _("Could not parse zone key file `%s'\n"),
2216 c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
2217 c->privkey = privkey;
2218 GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
2219 GNUNET_CRYPTO_short_hash (&pubkey,
2220 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2223 "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
2224 GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
2225 GNUNET_assert (GNUNET_OK ==
2226 GNUNET_CONTAINER_multihashmap_put (zonekeys, &long_hash, c,
2227 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2234 * Process namestore requests.
2236 * @param cls closure
2237 * @param server the initialized server
2238 * @param cfg configuration to use
2241 run (void *cls, struct GNUNET_SERVER_Handle *server,
2242 const struct GNUNET_CONFIGURATION_Handle *cfg)
2244 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2245 {&handle_start, NULL,
2246 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2247 {&handle_lookup_name, NULL,
2248 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2249 {&handle_record_put, NULL,
2250 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2251 {&handle_record_create, NULL,
2252 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2253 {&handle_record_remove, NULL,
2254 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2255 {&handle_zone_to_name, NULL,
2256 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
2257 {&handle_iteration_start, NULL,
2258 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage) },
2259 {&handle_iteration_next, NULL,
2260 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, sizeof (struct ZoneIterationNextMessage) },
2261 {&handle_iteration_stop, NULL,
2262 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage) },
2266 unsigned int counter;
2268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2271 /* Load private keys from disk */
2273 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore",
2274 "zonefile_directory",
2275 &zonefile_directory))
2277 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2278 _("No directory to load zonefiles specified in configuration\n"));
2279 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2283 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2285 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2288 _("Creating directory `%s' for zone files failed!\n"),
2289 zonefile_directory);
2290 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2294 "Created directory `%s' for zone files\n",
2295 zonefile_directory);
2298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2299 "Scanning directory `%s' for zone files\n", zonefile_directory);
2300 zonekeys = GNUNET_CONTAINER_multihashmap_create (16);
2302 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2304 "Found %u zone files\n",
2307 /* Loading database plugin */
2309 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2311 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2313 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2314 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2315 GNUNET_free (database);
2316 if (NULL == GSN_database)
2318 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2319 "Could not load database backend `%s'\n",
2321 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2325 /* Configuring server handles */
2326 GNUNET_SERVER_add_handlers (server, handlers);
2327 snc = GNUNET_SERVER_notification_context_create (server, 16);
2328 GNUNET_SERVER_disconnect_notify (server,
2329 &client_disconnect_notification,
2331 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2337 * The main function for the template service.
2339 * @param argc number of arguments from the command line
2340 * @param argv command line arguments
2341 * @return 0 ok, 1 on error
2344 main (int argc, char *const *argv)
2346 return (GNUNET_OK ==
2347 GNUNET_SERVICE_run (argc, argv, "namestore",
2348 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2351 /* end of gnunet-service-namestore.c */