2 This file is part of GNUnet.
3 (C) 2009 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
84 * Which flags must be included
86 uint16_t must_have_flags;
89 * Which flags must not be included
91 uint16_t must_not_have_flags;
98 struct GNUNET_NAMESTORE_Client
101 * Next element in the DLL
103 struct GNUNET_NAMESTORE_Client *next;
106 * Previous element in the DLL
108 struct GNUNET_NAMESTORE_Client *prev;
113 struct GNUNET_SERVER_Client *client;
117 * Zone iteration operations in progress initiated by this client
119 struct GNUNET_NAMESTORE_ZoneIteration *op_head;
123 * Zone iteration operations in progress initiated by this client
125 struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
130 * A container struct to store information belonging to a zone crypto key pair
132 struct GNUNET_NAMESTORE_CryptoContainer
135 * Filename where to store the container
140 * Short hash of the zone's public key
142 struct GNUNET_CRYPTO_ShortHashCode zone;
147 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
152 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
157 * Configuration handle.
159 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
164 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
169 static char *zonefile_directory;
172 * Name of the database plugin
174 static char *db_lib_name;
178 * Our notification context.
180 static struct GNUNET_SERVER_NotificationContext *snc;
183 * Head of the Client DLL
185 static struct GNUNET_NAMESTORE_Client *client_head;
188 * Tail of the Client DLL
190 static struct GNUNET_NAMESTORE_Client *client_tail;
193 * Hashmap containing the zone keys this namestore has is authoritative for
195 * Keys are the GNUNET_CRYPTO_HashCode of the GNUNET_CRYPTO_ShortHashCode
196 * The values are 'struct GNUNET_NAMESTORE_CryptoContainer *'
198 struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
202 * Writes the encrypted private key of a zone in a file
204 * @param filename where to store the zone
205 * @param c the crypto container containing private key of the zone
206 * @return GNUNET_OK on success, GNUNET_SYSERR on fail
209 write_key_to_file (const char *filename, struct GNUNET_NAMESTORE_CryptoContainer *c)
211 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
212 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
213 struct GNUNET_DISK_FileHandle *fd;
215 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
217 struct GNUNET_CRYPTO_ShortHashCode zone;
218 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
219 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
221 privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 _("File zone `%s' but corrupt content already exists, failed to write! \n"), GNUNET_short_h2s (&zone));
226 return GNUNET_SYSERR;
229 GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
230 GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
231 GNUNET_CRYPTO_rsa_key_free (privkey);
233 if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
235 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
236 _("File zone `%s' containing this key already exists\n"), GNUNET_short_h2s (&zone));
241 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
242 _("File zone `%s' but different zone key already exists, failed to write! \n"), GNUNET_short_h2s (&zone));
246 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
251 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
253 /* must exist but not be accessible, fail for good! */
254 if (0 != ACCESS (filename, R_OK))
255 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
257 GNUNET_break (0); /* what is going on!? */
258 return GNUNET_SYSERR;
261 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
262 return GNUNET_SYSERR;
265 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
267 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
268 return GNUNET_SYSERR;
270 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
271 GNUNET_assert (enc != NULL);
272 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
274 GNUNET_DISK_file_sync (fd);
275 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
276 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
277 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280 _("Stored zonekey for zone `%s' in file `%s'\n"), GNUNET_short_h2s(&c->zone), c->filename);
286 * Write all zone keys to disk.
287 * Iterates over all entries of the hashmap 'zonekeys'
290 * @param key zone key
291 * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
293 * @return GNUNET_OK to continue iteration
296 zone_to_disk_it (void *cls,
297 const struct GNUNET_HashCode *key,
300 struct GNUNET_NAMESTORE_CryptoContainer *c = value;
301 if (c->filename != NULL)
302 write_key_to_file(c->filename, c);
305 GNUNET_asprintf(&c->filename, "%s/%s.zkey", zonefile_directory, GNUNET_short_h2s (&c->zone));
306 write_key_to_file(c->filename, c);
309 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
310 GNUNET_CRYPTO_rsa_key_free (c->privkey);
311 GNUNET_free (c->pubkey);
312 GNUNET_free (c->filename);
320 * Returns the expiration time of the given block of records
321 * The block expiration time is the expiration time of the block with smallest
324 * @param rd_count number of records given in 'rd'
325 * @param rd array of records
326 * @return absolute expiration time
328 static struct GNUNET_TIME_Absolute
329 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
332 struct GNUNET_TIME_Absolute expire = GNUNET_TIME_UNIT_FOREVER_ABS;
333 struct GNUNET_TIME_Absolute at;
334 struct GNUNET_TIME_Relative rt;
337 return GNUNET_TIME_UNIT_ZERO_ABS;
338 for (c = 0; c < rd_count; c++)
340 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
342 rt.rel_value = rd[c].expiration_time;
343 at = GNUNET_TIME_relative_to_absolute (rt);
347 at.abs_value = rd[c].expiration_time;
349 expire = GNUNET_TIME_absolute_min (at, expire);
355 * Task run during shutdown.
361 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
364 struct GNUNET_NAMESTORE_ZoneIteration *no;
365 struct GNUNET_NAMESTORE_ZoneIteration *tmp;
366 struct GNUNET_NAMESTORE_Client *nc;
367 struct GNUNET_NAMESTORE_Client *next;
371 GNUNET_SERVER_notification_context_destroy (snc);
374 GNUNET_CONTAINER_multihashmap_iterate(zonekeys, &zone_to_disk_it, NULL);
375 GNUNET_CONTAINER_multihashmap_destroy(zonekeys);
377 for (nc = client_head; nc != NULL; nc = next)
380 for (no = nc->op_head; no != NULL; no = tmp)
382 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
386 GNUNET_SERVER_client_drop(nc->client);
387 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
391 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
392 GNUNET_free (db_lib_name);
393 GNUNET_free_non_null(zonefile_directory);
396 static struct GNUNET_NAMESTORE_Client *
397 client_lookup (struct GNUNET_SERVER_Client *client)
399 struct GNUNET_NAMESTORE_Client *nc;
401 GNUNET_assert (NULL != client);
403 for (nc = client_head; nc != NULL; nc = nc->next)
405 if (client == nc->client)
412 * Called whenever a client is disconnected.
413 * Frees our resources associated with that client.
416 * @param client identification of the client
419 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
421 struct GNUNET_NAMESTORE_ZoneIteration *no;
422 struct GNUNET_NAMESTORE_Client *nc;
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
428 nc = client_lookup (client);
430 if ((NULL == client) || (NULL == nc))
436 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
441 GNUNET_SERVER_client_drop(nc->client);
442 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
448 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
451 * @param client GNUNET_SERVER_Client sending the message
452 * @param message unused
455 handle_start (void *cls,
456 struct GNUNET_SERVER_Client *client,
457 const struct GNUNET_MessageHeader *message)
459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
461 struct GNUNET_NAMESTORE_Client *nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
463 GNUNET_SERVER_notification_context_add (snc, client);
464 GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
465 GNUNET_SERVER_client_keep (client);
466 GNUNET_SERVER_receive_done (client, GNUNET_OK);
470 struct LookupNameContext
473 struct GNUNET_NAMESTORE_Client *nc;
475 uint32_t record_type;
476 struct GNUNET_CRYPTO_ShortHashCode *zone;
482 handle_lookup_name_it (void *cls,
483 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
484 struct GNUNET_TIME_Absolute expire,
486 unsigned int rd_count,
487 const struct GNUNET_NAMESTORE_RecordData *rd,
488 const struct GNUNET_CRYPTO_RsaSignature *signature)
491 struct LookupNameContext *lnc = cls;
492 struct LookupNameResponseMessage *lnr_msg;
493 struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
494 struct GNUNET_NAMESTORE_CryptoContainer *cc;
495 struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
496 struct GNUNET_TIME_Absolute e;
497 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
498 struct GNUNET_HashCode long_hash;
505 int copied_elements = 0;
506 int contains_signature = GNUNET_NO;
507 int authoritative = GNUNET_NO;
511 name_len = strlen(name) + 1;
513 /* count records to copy */
516 if (lnc->record_type != 0)
518 /* special record type needed */
519 for (c = 0; c < rd_count; c ++)
520 if (rd[c].record_type == lnc->record_type)
521 copied_elements++; /* found matching record */
522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
523 copied_elements, lnc->record_type, lnc->name, GNUNET_short_h2s(lnc->zone));
524 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
526 for (c = 0; c < rd_count; c ++)
528 if (rd[c].record_type == lnc->record_type)
530 /* found matching record */
531 memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
538 copied_elements = rd_count;
539 rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
547 expire = GNUNET_TIME_UNIT_ZERO_ABS;
550 rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
551 char rd_ser[rd_ser_len];
552 GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
555 copied_elements, lnc->name, GNUNET_short_h2s(lnc->zone));
557 if ((copied_elements == rd_count) && (NULL != signature))
558 contains_signature = GNUNET_YES; /* returning all records, so include signature */
560 contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
563 if ((NULL != zone_key) && (copied_elements == rd_count))
565 GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash);
566 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
567 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
569 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
570 e = get_block_expiration_time(rd_count, rd);
571 signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count);
572 GNUNET_assert (signature_new != NULL);
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for name `%s' with %u records in zone `%s'\n",name, copied_elements, GNUNET_short_h2s(&zone_key_hash));
574 authoritative = GNUNET_YES;
577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am not authoritative for name `%s' in zone `%s'\n",name, GNUNET_short_h2s(&zone_key_hash));
580 r_size = sizeof (struct LookupNameResponseMessage) +
581 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
585 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
586 lnr_msg = GNUNET_malloc (r_size);
587 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
588 lnr_msg->gns_header.header.size = ntohs (r_size);
589 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
590 lnr_msg->rd_count = htons (copied_elements);
591 lnr_msg->rd_len = htons (rd_ser_len);
592 lnr_msg->name_len = htons (name_len);
593 lnr_msg->expire = GNUNET_TIME_absolute_hton(get_block_expiration_time(copied_elements, rd_selected));
595 if (rd_selected != rd)
596 GNUNET_free (rd_selected);
598 if (zone_key != NULL)
599 lnr_msg->public_key = (*zone_key);
601 memset(&lnr_msg->public_key, '\0', sizeof (lnr_msg->public_key));
603 if (GNUNET_YES == authoritative)
604 { /* use new created signature */
605 lnr_msg->contains_sig = htons (GNUNET_YES);
606 GNUNET_assert (signature_new != NULL);
607 lnr_msg->signature = *signature_new;
608 GNUNET_free (signature_new);
610 else if (GNUNET_YES == contains_signature)
612 /* use existing signature */
613 lnr_msg->contains_sig = htons (GNUNET_YES);
614 GNUNET_assert (signature != NULL);
615 lnr_msg->signature = *signature;
619 /* use no signature */
620 memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature));
623 name_tmp = (char *) &lnr_msg[1];
624 rd_tmp = &name_tmp[name_len];
626 memcpy (name_tmp, name, name_len);
627 memcpy (rd_tmp, rd_ser, rd_ser_len);
629 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
630 GNUNET_free (lnr_msg);
634 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
637 * @param client GNUNET_SERVER_Client sending the message
638 * @param message message of type 'struct LookupNameMessage'
641 handle_lookup_name (void *cls,
642 struct GNUNET_SERVER_Client *client,
643 const struct GNUNET_MessageHeader *message)
645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
646 struct LookupNameContext lnc;
647 struct GNUNET_NAMESTORE_Client *nc;
653 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
656 GNUNET_SERVER_receive_done (client, GNUNET_OK);
660 nc = client_lookup(client);
664 GNUNET_SERVER_receive_done (client, GNUNET_OK);
668 struct LookupNameMessage *ln_msg = (struct LookupNameMessage *) message;
669 rid = ntohl (ln_msg->gns_header.r_id);
670 name_len = ntohl (ln_msg->name_len);
671 type = ntohl (ln_msg->record_type);
673 if ((name_len == 0) || (name_len > 256))
676 GNUNET_SERVER_receive_done (client, GNUNET_OK);
680 name = (char *) &ln_msg[1];
681 if (name[name_len -1] != '\0')
684 GNUNET_SERVER_receive_done (client, GNUNET_OK);
689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_short_h2s(&ln_msg->zone));
691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up records with type %u for name `%s' in zone `%s'\n", type, name, GNUNET_short_h2s(&ln_msg->zone));
693 /* do the actual lookup */
694 lnc.request_id = rid;
696 lnc.record_type = type;
698 lnc.zone = &ln_msg->zone;
699 GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
701 GNUNET_SERVER_receive_done (client, GNUNET_OK);
706 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
709 * @param client GNUNET_SERVER_Client sending the message
710 * @param message message of type 'struct RecordPutMessage'
713 handle_record_put (void *cls,
714 struct GNUNET_SERVER_Client *client,
715 const struct GNUNET_MessageHeader *message)
717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
718 struct GNUNET_NAMESTORE_Client *nc;
719 struct RecordPutMessage *rp_msg;
720 struct GNUNET_TIME_Absolute expire;
721 struct GNUNET_CRYPTO_RsaSignature *signature;
722 struct RecordPutResponseMessage rpr_msg;
723 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
732 int res = GNUNET_SYSERR;
734 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
737 GNUNET_SERVER_receive_done (client, GNUNET_OK);
741 nc = client_lookup (client);
745 GNUNET_SERVER_receive_done (client, GNUNET_OK);
749 rp_msg = (struct RecordPutMessage *) message;
750 rid = ntohl (rp_msg->gns_header.r_id);
751 msg_size = ntohs (rp_msg->gns_header.header.size);
752 name_len = ntohs (rp_msg->name_len);
753 rd_count = ntohs (rp_msg->rd_count);
754 rd_ser_len = ntohs(rp_msg->rd_len);
756 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
759 GNUNET_SERVER_receive_done (client, GNUNET_OK);
763 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
766 GNUNET_SERVER_receive_done (client, GNUNET_OK);
770 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
771 if (msg_size != msg_size_exp)
773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
775 GNUNET_SERVER_receive_done (client, GNUNET_OK);
778 if ((name_len == 0) || (name_len > 256))
781 GNUNET_SERVER_receive_done (client, GNUNET_OK);
785 name = (char *) &rp_msg[1];
787 if (name[name_len -1] != '\0')
790 GNUNET_SERVER_receive_done (client, GNUNET_OK);
794 expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
795 signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
797 rd_ser = &name[name_len];
798 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
799 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
800 if (res != GNUNET_OK)
806 GNUNET_CRYPTO_short_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash);
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_short_h2s(&zone_hash));
809 /* Database operation */
810 res = GSN_database->put_records(GSN_database->cls,
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
818 name, (res == GNUNET_OK) ? "OK" : "FAIL");
822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
823 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
824 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
825 rpr_msg.gns_header.r_id = htonl (rid);
826 rpr_msg.op_result = htonl (res);
827 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
829 GNUNET_SERVER_receive_done (client, GNUNET_OK);
832 struct CreateRecordContext
834 struct GNUNET_NAMESTORE_RecordData *rd;
835 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
836 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
837 struct GNUNET_TIME_Absolute expire;
844 handle_create_record_it (void *cls,
845 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
846 struct GNUNET_TIME_Absolute expire,
848 unsigned int rd_count,
849 const struct GNUNET_NAMESTORE_RecordData *rd,
850 const struct GNUNET_CRYPTO_RsaSignature *signature)
852 struct CreateRecordContext *crc = cls;
853 struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
854 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
855 struct GNUNET_TIME_Absolute block_expiration;
857 int exist = GNUNET_SYSERR;
858 int update = GNUNET_NO;
860 int rd_count_new = 0;
862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
863 for (c = 0; c < rd_count; c++)
865 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) &&
866 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
868 /* Update unique PKEY */
873 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) &&
874 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
876 /* Update unique PSEU */
881 if ((crc->rd->record_type == rd[c].record_type) &&
882 (crc->rd->data_size == rd[c].data_size) &&
883 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
886 "Found existing records for `%s' to update expiration date!\n",
889 if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
890 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
891 == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
897 if (exist == GNUNET_SYSERR)
899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
900 "No existing record for name `%s'!\n",
902 rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
903 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
904 rd_count_new = rd_count + 1;
905 rd_new[rd_count] = *(crc->rd);
907 else if (update == GNUNET_NO)
909 /* Exact same record already exists */
910 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
911 "Matching record for %s' exists, no change required!\n",
919 GNUNET_assert (GNUNET_YES == update);
920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
921 "Updating existing records for `%s'!\n",
923 rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
924 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
925 rd_count_new = rd_count;
926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
927 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
928 ? "Updating absolute expiration from %llu to %llu!\n"
929 : "Updating relative expiration from %llu to %llu!\n",
930 rd_new[exist].expiration_time, crc->rd->expiration_time);
931 rd_new[exist] = *(crc->rd);
934 block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
935 if (block_expiration.abs_value != expire.abs_value)
936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
937 "Updated block expiration time\n");
939 memset (&dummy_signature, '\0', sizeof (dummy_signature));
941 /* Database operation */
942 GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
943 res = GSN_database->put_records(GSN_database->cls,
944 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
947 rd_count_new, rd_new,
949 GNUNET_break (GNUNET_OK == res);
950 if (res == GNUNET_OK)
951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
953 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
957 GNUNET_free_non_null (rd_new);
961 /* failed to create the record */
962 crc->res = GNUNET_SYSERR;
965 /* database operations OK */
966 if (GNUNET_YES == update)
968 /* we updated an existing record */
969 crc->res = GNUNET_NO;
973 /* we created a new record */
974 crc->res = GNUNET_YES;
978 /* identical entry existed, so we did nothing */
979 crc->res = GNUNET_NO;
984 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
989 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
992 * @param client GNUNET_SERVER_Client sending the message
993 * @param message message of type 'struct RecordCreateMessage'
996 handle_record_create (void *cls,
997 struct GNUNET_SERVER_Client *client,
998 const struct GNUNET_MessageHeader *message)
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1001 struct GNUNET_NAMESTORE_Client *nc;
1002 struct RecordCreateMessage *rp_msg;
1003 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1004 struct CreateRecordContext crc;
1005 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1006 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1007 struct RecordCreateResponseMessage rcr_msg;
1008 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1009 struct GNUNET_HashCode long_hash;
1012 size_t msg_size_exp;
1021 int res = GNUNET_SYSERR;
1022 crc.res = GNUNET_SYSERR;
1024 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1026 GNUNET_break_op (0);
1027 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1031 nc = client_lookup(client);
1034 GNUNET_break_op (0);
1035 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1039 rp_msg = (struct RecordCreateMessage *) message;
1040 rid = ntohl (rp_msg->gns_header.r_id);
1041 name_len = ntohs (rp_msg->name_len);
1042 msg_size = ntohs (message->size);
1043 rd_count = ntohs (rp_msg->rd_count);
1044 rd_ser_len = ntohs (rp_msg->rd_len);
1045 key_len = ntohs (rp_msg->pkey_len);
1046 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1048 if (msg_size != msg_size_exp)
1050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1051 GNUNET_break_op (0);
1052 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1056 if ((name_len == 0) || (name_len > 256))
1058 GNUNET_break_op (0);
1059 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1063 pkey_tmp = (char *) &rp_msg[1];
1064 name_tmp = &pkey_tmp[key_len];
1065 rd_ser = &name_tmp[name_len];
1067 if (name_tmp[name_len -1] != '\0')
1069 GNUNET_break_op (0);
1070 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1074 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1076 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1077 if ((res != GNUNET_OK) || (rd_count != 1))
1079 GNUNET_break_op (0);
1082 /* Extracting and converting private key */
1083 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1084 GNUNET_assert (pkey != NULL);
1085 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1086 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1087 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1089 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash));
1093 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1094 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1095 cc->pubkey = GNUNET_malloc(sizeof (pub));
1096 memcpy (cc->pubkey, &pub, sizeof(pub));
1097 cc->zone = pubkey_hash;
1098 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1101 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1102 crc.res = GNUNET_SYSERR;
1106 crc.name = name_tmp;
1108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1110 /* Get existing records for name */
1111 res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
1112 if (res != GNUNET_SYSERR)
1114 GNUNET_CRYPTO_rsa_key_free(pkey);
1119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1120 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1121 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1122 rcr_msg.gns_header.r_id = htonl (rid);
1123 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1124 rcr_msg.op_result = htonl (GNUNET_YES);
1125 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1126 rcr_msg.op_result = htonl (GNUNET_NO);
1128 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1129 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
1131 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1135 struct RemoveRecordContext
1137 struct GNUNET_NAMESTORE_RecordData *rd;
1138 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1144 handle_record_remove_it (void *cls,
1145 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1146 struct GNUNET_TIME_Absolute expire,
1148 unsigned int rd_count,
1149 const struct GNUNET_NAMESTORE_RecordData *rd,
1150 const struct GNUNET_CRYPTO_RsaSignature *signature)
1152 struct RemoveRecordContext *rrc = cls;
1156 unsigned int rd_count_new;
1158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
1162 /* Could not find record to remove */
1167 /* Find record to remove */
1168 found = GNUNET_SYSERR;
1169 for (c = 0; c < rd_count; c++)
1172 if (rd[c].flags != rrc->rd->flags)
1174 if (rd[c].record_type != rrc->rd->record_type)
1177 if (rd[c].data_size != rrc->rd->data_size)
1180 if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1187 if (GNUNET_SYSERR == found)
1189 /* Could not find record to remove */
1194 if (rd_count-1 == 0)
1196 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1197 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1198 res = GSN_database->remove_records (GSN_database->cls,
1201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1202 "No records left for name `%s', removing name\n",
1204 if (GNUNET_OK != res)
1206 /* Could put records into database */
1214 rd_count_new = rd_count -1;
1215 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1217 unsigned int c2 = 0;
1218 for (c = 0; c < rd_count; c++)
1222 GNUNET_assert (c2 < rd_count_new);
1228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1230 /* Create dummy signature */
1231 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1232 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1236 res = GSN_database->put_records(GSN_database->cls,
1240 rd_count_new, rd_new,
1242 if (GNUNET_OK != res)
1244 /* Could put records into database */
1253 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1256 * @param client GNUNET_SERVER_Client sending the message
1257 * @param message message of type 'struct RecordRemoveMessage'
1260 handle_record_remove (void *cls,
1261 struct GNUNET_SERVER_Client *client,
1262 const struct GNUNET_MessageHeader *message)
1264 struct GNUNET_NAMESTORE_Client *nc;
1265 const struct RecordRemoveMessage *rr_msg;
1266 struct RecordRemoveResponseMessage rrr_msg;
1267 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1268 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1269 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1270 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1271 struct GNUNET_HashCode long_hash;
1272 const char *pkey_tmp;
1273 const char *name_tmp;
1279 size_t msg_size_exp = 0;
1283 int res = GNUNET_SYSERR;
1285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1286 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1288 GNUNET_break_op (0);
1289 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1293 nc = client_lookup(client);
1296 GNUNET_break_op (0);
1297 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1301 rr_msg = (const struct RecordRemoveMessage *) message;
1302 rid = ntohl (rr_msg->gns_header.r_id);
1303 name_len = ntohs (rr_msg->name_len);
1304 rd_ser_len = ntohs (rr_msg->rd_len);
1305 rd_count = ntohs (rr_msg->rd_count);
1306 key_len = ntohs (rr_msg->pkey_len);
1307 msg_size = ntohs (message->size);
1309 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1311 GNUNET_break_op (0);
1312 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1316 if ((name_len >=256) || (name_len == 0))
1318 GNUNET_break_op (0);
1319 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1323 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1324 if (msg_size != msg_size_exp)
1326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1327 GNUNET_break_op (0);
1328 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1332 pkey_tmp = (const char *) &rr_msg[1];
1333 name_tmp = &pkey_tmp[key_len];
1334 rd_ser = &name_tmp[name_len];
1337 if ((name_len == 0) || (name_len > 256))
1339 GNUNET_break_op (0);
1340 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1344 if (name_tmp[name_len -1] != '\0')
1346 GNUNET_break_op (0);
1347 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1351 /* Extracting and converting private key */
1352 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1353 GNUNET_assert (pkey != NULL);
1354 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1355 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1356 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1358 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1361 "Received new private key for zone `%s'\n",
1362 GNUNET_short_h2s(&pubkey_hash));
1363 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1364 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1365 cc->pubkey = GNUNET_malloc(sizeof (pub));
1366 memcpy (cc->pubkey, &pub, sizeof(pub));
1367 cc->zone = pubkey_hash;
1369 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1373 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1374 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1375 if ((res != GNUNET_OK) || (rd_count > 1))
1377 GNUNET_break_op (0);
1383 /* remove the whole name and all records */
1384 /* Database operation */
1385 res = GSN_database->remove_records (GSN_database->cls,
1388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1389 name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1391 if (GNUNET_OK != res)
1392 /* Could not remove entry from database */
1399 /* remove a single record */
1400 struct RemoveRecordContext rrc;
1404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1406 /* Database operation */
1407 res = GSN_database->iterate_records (GSN_database->cls,
1411 handle_record_remove_it, &rrc);
1413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1414 name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1420 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1421 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1422 rrr_msg.gns_header.r_id = htonl (rid);
1423 rrr_msg.op_result = htonl (res);
1424 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1426 GNUNET_CRYPTO_rsa_key_free (pkey);
1428 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1432 struct ZoneToNameCtx
1434 struct GNUNET_NAMESTORE_Client *nc;
1439 handle_zone_to_name_it (void *cls,
1440 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1441 struct GNUNET_TIME_Absolute expire,
1443 unsigned int rd_count,
1444 const struct GNUNET_NAMESTORE_RecordData *rd,
1445 const struct GNUNET_CRYPTO_RsaSignature *signature)
1447 struct ZoneToNameCtx *ztn_ctx = cls;
1448 struct ZoneToNameResponseMessage *ztnr_msg;
1449 int16_t res = GNUNET_SYSERR;
1450 uint16_t name_len = 0;
1451 uint16_t rd_ser_len = 0 ;
1452 int32_t contains_sig = 0;
1453 size_t msg_size = 0;
1455 char *rd_ser = NULL;
1460 if ((zone_key != NULL) && (name != NULL))
1463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1465 name_len = strlen (name) +1;
1469 /* no result found */
1470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1477 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1478 rd_ser = GNUNET_malloc (rd_ser_len);
1479 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1484 if (signature != NULL)
1485 contains_sig = GNUNET_YES;
1487 contains_sig = GNUNET_NO;
1491 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1492 ztnr_msg = GNUNET_malloc (msg_size);
1494 name_tmp = (char *) &ztnr_msg[1];
1495 rd_tmp = &name_tmp[name_len];
1496 sig_tmp = &rd_tmp[rd_ser_len];
1498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1499 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1500 ztnr_msg->gns_header.header.size = htons (msg_size);
1501 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1502 ztnr_msg->res = htons (res);
1503 ztnr_msg->rd_len = htons (rd_ser_len);
1504 ztnr_msg->rd_count = htons (rd_count);
1505 ztnr_msg->name_len = htons (name_len);
1506 ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1507 if (zone_key != NULL)
1508 ztnr_msg->zone_key = *zone_key;
1510 memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1512 if ((name_len > 0) && (name != NULL))
1513 memcpy (name_tmp, name, name_len);
1515 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);
1516 if ((rd_ser_len > 0) && (rd_ser != NULL))
1517 memcpy (rd_tmp, rd_ser, rd_ser_len);
1518 if ((GNUNET_YES == contains_sig) && (signature != NULL))
1519 memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1521 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1522 GNUNET_free (ztnr_msg);
1523 GNUNET_free_non_null (rd_ser);
1527 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1530 * @param client GNUNET_SERVER_Client sending the message
1531 * @param message message of type 'struct ZoneToNameMessage'
1534 handle_zone_to_name (void *cls,
1535 struct GNUNET_SERVER_Client *client,
1536 const struct GNUNET_MessageHeader *message)
1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1539 struct GNUNET_NAMESTORE_Client *nc;
1540 struct ZoneToNameMessage *ztn_msg;
1541 struct ZoneToNameCtx ztn_ctx;
1542 size_t msg_size = 0;
1545 if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1547 GNUNET_break_op (0);
1548 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1552 nc = client_lookup(client);
1555 GNUNET_break_op (0);
1556 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1560 ztn_msg = (struct ZoneToNameMessage *) message;
1562 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1564 GNUNET_break_op (0);
1565 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1569 rid = ntohl (ztn_msg->gns_header.r_id);
1574 struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1575 GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1578 GNUNET_short_h2s (&ztn_msg->value_zone));
1580 GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1582 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1587 * Copy record, data has to be free separetely
1590 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1593 memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1594 dest->data = GNUNET_malloc (src->data_size);
1595 memcpy ((void *) dest->data, src->data, src->data_size);
1598 struct ZoneIterationProcResult
1600 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1602 int res_iteration_finished;
1603 int records_included;
1607 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1608 struct GNUNET_NAMESTORE_RecordData *rd;
1609 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1610 struct GNUNET_CRYPTO_RsaSignature signature;
1611 struct GNUNET_TIME_Absolute expire;
1616 zone_iteraterate_proc (void *cls,
1617 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1618 struct GNUNET_TIME_Absolute expire,
1620 unsigned int rd_count,
1621 const struct GNUNET_NAMESTORE_RecordData *rd,
1622 const struct GNUNET_CRYPTO_RsaSignature *signature)
1624 struct ZoneIterationProcResult *proc = cls;
1625 struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1626 struct GNUNET_CRYPTO_RsaSignature *new_signature;
1627 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1628 struct GNUNET_CRYPTO_ShortHashCode hash;
1629 struct GNUNET_HashCode long_hash;
1630 struct GNUNET_TIME_Absolute e;
1631 unsigned int rd_count_filtered = 0;
1635 proc->res_iteration_finished = GNUNET_NO;
1636 proc->records_included = 0;
1638 if ((zone_key == NULL) && (name == NULL))
1640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1641 proc->res_iteration_finished = GNUNET_YES;
1645 else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1647 rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1648 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1649 for (c = 0; c < rd_count; c++)
1651 include = GNUNET_YES;
1652 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1653 c, rd[c].flags, proc->zi->must_have_flags);
1654 /* Checking must have flags */
1655 if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1663 include = GNUNET_NO;
1666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1667 c, rd[c].flags, proc->zi->must_not_have_flags);
1668 if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1671 include = GNUNET_NO;
1676 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1678 if (GNUNET_YES == include)
1680 copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1681 rd_count_filtered++;
1685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1687 proc->records_included = rd_count_filtered;
1688 if (0 == rd_count_filtered)
1690 GNUNET_free (rd_filtered);
1693 proc->rd = rd_filtered;
1694 proc->name = GNUNET_strdup(name);
1695 memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1698 proc->has_signature = GNUNET_NO;
1699 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1700 GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1701 proc->zone_hash = hash;
1703 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1705 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1706 e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1708 new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1709 GNUNET_assert (signature != NULL);
1710 proc->signature = (*new_signature);
1711 GNUNET_free (new_signature);
1712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1713 name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1714 proc->has_signature = GNUNET_YES;
1716 else if (rd_count_filtered == rd_count)
1718 proc->expire = expire;
1719 if (NULL != signature)
1721 proc->signature = (*signature);
1722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1723 name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1724 proc->has_signature = GNUNET_YES;
1728 memset (&proc->signature, '\0', sizeof (proc->signature));
1729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1742 find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1745 struct GNUNET_CRYPTO_ShortHashCode *zone;
1747 if (GNUNET_YES == proc->zi->has_zone)
1748 zone = &proc->zi->zone;
1754 GSN_database->iterate_records (GSN_database->cls, zone , NULL, proc->zi->offset, &zone_iteraterate_proc, proc);
1757 while ((proc->records_included == 0) && (GNUNET_NO == proc->res_iteration_finished));
1762 send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1764 struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1766 if (GNUNET_YES == proc->res_iteration_finished)
1768 struct ZoneIterationResponseMessage zir_msg;
1769 if (zi->has_zone == GNUNET_YES)
1770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_short_h2s(&zi->zone));
1772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n");
1774 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE");
1775 zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1776 zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1777 zir_msg.gns_header.r_id = htonl(zi->request_id);
1778 zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
1779 zir_msg.name_len = htons (0);
1780 zir_msg.reserved = htons (0);
1781 zir_msg.rd_count = htons (0);
1782 zir_msg.rd_len = htons (0);
1783 memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key));
1784 memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature));
1785 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1788 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1794 GNUNET_assert (proc->records_included > 0);
1796 struct ZoneIterationResponseMessage *zir_msg;
1797 if (zi->has_zone == GNUNET_YES)
1798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n",
1799 proc->name, GNUNET_short_h2s(&zi->zone));
1800 if (zi->has_zone == GNUNET_NO)
1801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n",
1809 name_len = strlen (proc->name) +1;
1811 rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);
1812 char rd_ser[rd_ser_len];
1813 GNUNET_NAMESTORE_records_serialize(proc->records_included, proc->rd, rd_ser_len, rd_ser);
1814 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1815 zir_msg = GNUNET_malloc(msg_size);
1817 name_tmp = (char *) &zir_msg[1];
1818 rd_tmp = &name_tmp[name_len];
1820 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1821 zir_msg->gns_header.header.size = htons (msg_size);
1822 zir_msg->gns_header.r_id = htonl(zi->request_id);
1823 zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire);
1824 zir_msg->reserved = htons (0);
1825 zir_msg->name_len = htons (name_len);
1826 zir_msg->rd_count = htons (proc->records_included);
1827 zir_msg->rd_len = htons (rd_ser_len);
1828 zir_msg->signature = proc->signature;
1829 zir_msg->public_key = proc->zone_key;
1830 memcpy (name_tmp, proc->name, name_len);
1831 memcpy (rd_tmp, rd_ser, rd_ser_len);
1833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size);
1834 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) zir_msg, GNUNET_NO);
1835 GNUNET_free (zir_msg);
1840 clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
1843 GNUNET_free_non_null (proc->name);
1844 for (c = 0; c < proc->records_included; c++)
1846 GNUNET_free ((void *) proc->rd[c].data);
1848 GNUNET_free_non_null (proc->rd);
1855 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
1858 * @param client GNUNET_SERVER_Client sending the message
1859 * @param message message of type 'struct ZoneIterationStartMessage'
1862 handle_iteration_start (void *cls,
1863 struct GNUNET_SERVER_Client *client,
1864 const struct GNUNET_MessageHeader *message)
1866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
1868 struct ZoneIterationStartMessage *zis_msg = (struct ZoneIterationStartMessage *) message;
1869 struct GNUNET_NAMESTORE_Client *nc;
1870 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1871 struct GNUNET_CRYPTO_ShortHashCode dummy;
1872 struct ZoneIterationProcResult proc;
1874 nc = client_lookup(client);
1877 GNUNET_break_op (0);
1878 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1882 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
1883 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1886 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
1887 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
1889 memset (&dummy, '\0', sizeof (dummy));
1890 if (0 == memcmp (&dummy, &zis_msg->zone, sizeof (dummy)))
1892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
1893 zi->zone = zis_msg->zone;
1894 zi->has_zone = GNUNET_NO;
1898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
1899 zi->zone = zis_msg->zone;
1900 zi->has_zone = GNUNET_YES;
1903 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1906 find_next_zone_iteration_result (&proc);
1907 if (GNUNET_YES == proc.res_iteration_finished)
1909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
1911 else if (proc.records_included != 0)
1913 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
1915 send_zone_iteration_result (&proc);
1916 clean_up_zone_iteration_result (&proc);
1918 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1923 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
1926 * @param client GNUNET_SERVER_Client sending the message
1927 * @param message message of type 'struct ZoneIterationStopMessage'
1930 handle_iteration_stop (void *cls,
1931 struct GNUNET_SERVER_Client *client,
1932 const struct GNUNET_MessageHeader *message)
1934 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1936 struct GNUNET_NAMESTORE_Client *nc;
1937 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1938 struct ZoneIterationStopMessage *zis_msg;
1941 nc = client_lookup(client);
1944 GNUNET_break_op (0);
1945 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1949 zis_msg = (struct ZoneIterationStopMessage *) message;
1950 rid = ntohl (zis_msg->gns_header.r_id);
1951 for (zi = nc->op_head; zi != NULL; zi = zi->next)
1953 if (zi->request_id == rid)
1958 GNUNET_break_op (0);
1959 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1963 GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1964 if (GNUNET_YES == zi->has_zone)
1965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_short_h2s (&zi->zone));
1967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration all zones\n");
1970 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1975 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
1978 * @param client GNUNET_SERVER_Client sending the message
1979 * @param message message of type 'struct ZoneIterationNextMessage'
1982 handle_iteration_next (void *cls,
1983 struct GNUNET_SERVER_Client *client,
1984 const struct GNUNET_MessageHeader *message)
1986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1988 struct GNUNET_NAMESTORE_Client *nc;
1989 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1990 struct ZoneIterationNextMessage *zis_msg;
1993 nc = client_lookup(client);
1996 GNUNET_break_op (0);
1997 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2001 zis_msg = (struct ZoneIterationNextMessage *) message;
2002 rid = ntohl (zis_msg->gns_header.r_id);
2003 for (zi = nc->op_head; zi != NULL; zi = zi->next)
2005 if (zi->request_id == rid)
2010 GNUNET_break_op (0);
2011 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2015 struct ZoneIterationProcResult proc;
2018 find_next_zone_iteration_result (&proc);
2019 if (GNUNET_YES == proc.res_iteration_finished)
2021 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
2023 else if (proc.records_included != 0)
2025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
2027 send_zone_iteration_result (&proc);
2028 clean_up_zone_iteration_result (&proc);
2030 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2034 zonekey_file_it (void *cls, const char *filename)
2036 struct GNUNET_HashCode long_hash;
2038 if ((filename != NULL) && (NULL != strstr(filename, ".zkey")))
2040 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2041 struct GNUNET_NAMESTORE_CryptoContainer *c;
2042 privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
2043 if (privkey == NULL)
2046 c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
2047 c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2048 c->privkey = privkey;
2049 GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
2050 GNUNET_CRYPTO_short_hash(c->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &c->zone);
2052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
2053 GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
2054 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2062 * Process template requests.
2064 * @param cls closure
2065 * @param server the initialized server
2066 * @param cfg configuration to use
2069 run (void *cls, struct GNUNET_SERVER_Handle *server,
2070 const struct GNUNET_CONFIGURATION_Handle *cfg)
2074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2076 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2077 {&handle_start, NULL,
2078 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2079 {&handle_lookup_name, NULL,
2080 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2081 {&handle_record_put, NULL,
2082 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2083 {&handle_record_create, NULL,
2084 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2085 {&handle_record_remove, NULL,
2086 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2087 {&handle_zone_to_name, NULL,
2088 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
2089 {&handle_iteration_start, NULL,
2090 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
2091 {&handle_iteration_next, NULL,
2092 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
2093 {&handle_iteration_stop, NULL,
2094 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0},
2100 /* Load private keys from disk */
2102 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", "zonefile_directory",
2103 &zonefile_directory))
2105 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No directory to load zonefiles specified in configuration\n"));
2106 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2110 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2112 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2114 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Creating directory `%s' for zone files failed!\n"), zonefile_directory);
2115 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created directory `%s' for zone files\n", zonefile_directory);
2121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scanning directory `%s' for zone files\n", zonefile_directory);
2122 zonekeys = GNUNET_CONTAINER_multihashmap_create (10);
2123 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u zone files\n", counter);
2126 /* Loading database plugin */
2128 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2132 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2133 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2134 GNUNET_free (database);
2135 if (GSN_database == NULL)
2137 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
2139 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2143 /* Configuring server handles */
2144 GNUNET_SERVER_add_handlers (server, handlers);
2145 snc = GNUNET_SERVER_notification_context_create (server, 16);
2146 GNUNET_SERVER_disconnect_notify (server,
2147 &client_disconnect_notification,
2150 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2157 * The main function for the template service.
2159 * @param argc number of arguments from the command line
2160 * @param argv command line arguments
2161 * @return 0 ok, 1 on error
2164 main (int argc, char *const *argv)
2166 return (GNUNET_OK ==
2167 GNUNET_SERVICE_run (argc, argv, "namestore",
2168 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2171 /* end of gnunet-service-namestore.c */