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;
151 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
156 * Configuration handle.
158 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
163 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
168 static char *zonefile_directory;
171 * Name of the database plugin
173 static char *db_lib_name;
176 * Our notification context.
178 static struct GNUNET_SERVER_NotificationContext *snc;
181 * Head of the Client DLL
183 static struct GNUNET_NAMESTORE_Client *client_head;
186 * Tail of the Client DLL
188 static struct GNUNET_NAMESTORE_Client *client_tail;
191 * Hashmap containing the zone keys this namestore has is authoritative for
193 * Keys are the GNUNET_CRYPTO_HashCode of the GNUNET_CRYPTO_ShortHashCode
194 * The values are 'struct GNUNET_NAMESTORE_CryptoContainer *'
196 static struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
200 * Writes the encrypted private key of a zone in a file
202 * @param filename where to store the zone
203 * @param c the crypto container containing private key of the zone
204 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
207 write_key_to_file (const char *filename,
208 struct GNUNET_NAMESTORE_CryptoContainer *c)
210 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
211 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
212 struct GNUNET_DISK_FileHandle *fd;
213 struct GNUNET_CRYPTO_ShortHashCode zone;
214 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
215 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
217 fd = GNUNET_DISK_file_open (filename,
218 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS,
219 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
220 if ( (NULL == fd) && (EEXIST == errno) )
222 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
225 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
226 _("Failed to write zone key to file `%s': %s\n"),
228 _("file exists but reading key failed"));
229 return GNUNET_SYSERR;
231 GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
232 GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
233 GNUNET_CRYPTO_rsa_key_free (privkey);
234 if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
237 "File zone `%s' containing this key already exists\n",
238 GNUNET_short_h2s (&zone));
241 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
242 _("Failed to write zone key to file `%s': %s\n"),
244 _("file exists with different key"));
249 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
250 return GNUNET_SYSERR;
252 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
254 GNUNET_break (GNUNET_YES == GNUNET_DISK_file_close (fd));
255 return GNUNET_SYSERR;
257 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
258 GNUNET_assert (NULL != enc);
259 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
261 GNUNET_DISK_file_sync (fd);
262 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
263 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
264 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
266 "Stored zonekey for zone `%s' in file `%s'\n",
267 GNUNET_short_h2s(&c->zone), c->filename);
273 * Write allthe given zone key to disk and then removes the entry from the
274 * 'zonekeys' hash map.
277 * @param key zone key
278 * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
280 * @return GNUNET_OK to continue iteration
283 zone_to_disk_it (void *cls,
284 const struct GNUNET_HashCode *key,
287 struct GNUNET_NAMESTORE_CryptoContainer *c = value;
289 if (NULL == c->filename)
290 GNUNET_asprintf(&c->filename,
293 GNUNET_short_h2s (&c->zone));
294 (void) write_key_to_file(c->filename, c);
295 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
296 GNUNET_CRYPTO_rsa_key_free (c->privkey);
297 GNUNET_free (c->pubkey);
298 GNUNET_free (c->filename);
305 * Returns the expiration time of the given block of records. The block
306 * expiration time is the expiration time of the block with smallest
309 * @param rd_count number of records given in 'rd'
310 * @param rd array of records
311 * @return absolute expiration time
313 static struct GNUNET_TIME_Absolute
314 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
317 struct GNUNET_TIME_Absolute expire;
318 struct GNUNET_TIME_Absolute at;
319 struct GNUNET_TIME_Relative rt;
322 return GNUNET_TIME_UNIT_ZERO_ABS;
323 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
324 for (c = 0; c < rd_count; c++)
326 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
328 rt.rel_value = rd[c].expiration_time;
329 at = GNUNET_TIME_relative_to_absolute (rt);
333 at.abs_value = rd[c].expiration_time;
335 expire = GNUNET_TIME_absolute_min (at, expire);
342 * Task run during shutdown.
348 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
350 struct GNUNET_NAMESTORE_ZoneIteration *no;
351 struct GNUNET_NAMESTORE_Client *nc;
353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
356 GNUNET_SERVER_notification_context_destroy (snc);
359 GNUNET_CONTAINER_multihashmap_iterate (zonekeys, &zone_to_disk_it, NULL);
360 GNUNET_CONTAINER_multihashmap_destroy (zonekeys);
362 while (NULL != (nc = client_head))
364 while (NULL != (no = nc->op_head))
366 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
369 GNUNET_SERVER_client_drop(nc->client);
370 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
373 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
374 GNUNET_free (db_lib_name);
376 GNUNET_free_non_null (zonefile_directory);
377 zonefile_directory = NULL;
382 * Lookup our internal data structure for a given client.
384 * @param client server client handle to use for the lookup
385 * @return our internal structure for the client, NULL if
386 * we do not have any yet
388 static struct GNUNET_NAMESTORE_Client *
389 client_lookup (struct GNUNET_SERVER_Client *client)
391 struct GNUNET_NAMESTORE_Client *nc;
393 GNUNET_assert (NULL != client);
394 for (nc = client_head; NULL != nc; nc = nc->next)
395 if (client == nc->client)
402 * Called whenever a client is disconnected.
403 * Frees our resources associated with that client.
406 * @param client identification of the client
409 client_disconnect_notification (void *cls,
410 struct GNUNET_SERVER_Client *client)
412 struct GNUNET_NAMESTORE_ZoneIteration *no;
413 struct GNUNET_NAMESTORE_Client *nc;
417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
418 "Client %p disconnected\n",
420 nc = client_lookup (client);
423 while (NULL != (no = nc->op_head))
425 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
428 GNUNET_SERVER_client_drop (nc->client);
429 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
435 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
438 * @param client GNUNET_SERVER_Client sending the message
439 * @param message unused
442 handle_start (void *cls,
443 struct GNUNET_SERVER_Client *client,
444 const struct GNUNET_MessageHeader *message)
446 struct GNUNET_NAMESTORE_Client *nc;
448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
449 "Client %p connected\n", client);
450 if (NULL != client_lookup (client))
453 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
456 nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
458 GNUNET_SERVER_notification_context_add (snc, client);
459 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc);
460 GNUNET_SERVER_client_keep (client);
461 GNUNET_SERVER_receive_done (client, GNUNET_OK);
466 * Context for name lookups passed from 'handle_lookup_name' to
467 * 'handle_lookup_name_it' as closure
469 struct LookupNameContext
472 * The client to send the response to
474 struct GNUNET_NAMESTORE_Client *nc;
479 const struct GNUNET_CRYPTO_ShortHashCode *zone;
487 * Operation id for the name lookup
492 * Requested specific record type
494 uint32_t record_type;
499 * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
501 * @param cls a 'struct LookupNameContext *' with information about the request
502 * @param zone_key zone key of the zone
503 * @param expire expiration time
505 * @param rd_count number of records
506 * @param rd array of records
507 * @param signature signature
510 handle_lookup_name_it (void *cls,
511 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
512 struct GNUNET_TIME_Absolute expire,
514 unsigned int rd_count,
515 const struct GNUNET_NAMESTORE_RecordData *rd,
516 const struct GNUNET_CRYPTO_RsaSignature *signature)
518 struct LookupNameContext *lnc = cls;
519 struct LookupNameResponseMessage *lnr_msg;
520 struct GNUNET_NAMESTORE_RecordData *rd_selected;
521 struct GNUNET_NAMESTORE_CryptoContainer *cc;
522 struct GNUNET_CRYPTO_RsaSignature *signature_new;
523 struct GNUNET_TIME_Absolute e;
524 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
525 struct GNUNET_HashCode long_hash;
532 int contains_signature;
536 name_len = (NULL == name) ? 0 : strlen(name) + 1;
539 /* count records to copy */
540 if (0 != lnc->record_type)
542 /* special record type needed */
543 for (c = 0; c < rd_count; c++)
544 if (rd[c].record_type == lnc->record_type)
545 copied_elements++; /* found matching record */
546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
547 "Found %u records with type %u for name `%s' in zone `%s'\n",
551 GNUNET_short_h2s(lnc->zone));
552 if (copied_elements > 0)
554 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
556 for (c = 0; c < rd_count; c++)
558 if (rd[c].record_type == lnc->record_type)
560 /* found matching record */
561 rd_selected[copied_elements] = rd[c]; /* shallow copy! */
569 copied_elements = rd_count;
570 rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
572 // FIXME: need to adjust 'rd' from relative to absolute times!
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
574 "Found %u records for name `%s' in zone `%s'\n",
577 GNUNET_short_h2s (lnc->zone));
579 if ((copied_elements == rd_count) && (NULL != signature))
580 contains_signature = GNUNET_YES; /* returning all records, so include signature */
582 contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
584 authoritative = GNUNET_NO;
585 signature_new = NULL;
586 if ((NULL != zone_key) && (copied_elements == rd_count))
588 GNUNET_CRYPTO_short_hash (zone_key,
589 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
591 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
592 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash)))
594 e = get_block_expiration_time (rd_count, rd);
595 signature_new = GNUNET_NAMESTORE_create_signature (cc->privkey, e, name, rd, rd_count);
596 GNUNET_assert (NULL != signature_new);
597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
598 "Creating signature for name `%s' with %u records in zone `%s'\n",
601 GNUNET_short_h2s(&zone_key_hash));
602 authoritative = GNUNET_YES;
606 rd_ser_len = GNUNET_NAMESTORE_records_get_size (copied_elements, rd_selected);
607 r_size = sizeof (struct LookupNameResponseMessage) +
608 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
612 "Sending `%s' message\n",
613 "NAMESTORE_LOOKUP_NAME_RESPONSE");
614 lnr_msg = GNUNET_malloc (r_size);
615 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
616 lnr_msg->gns_header.header.size = ntohs (r_size);
617 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
618 lnr_msg->rd_count = htons (copied_elements);
619 lnr_msg->rd_len = htons (rd_ser_len);
620 lnr_msg->name_len = htons (name_len);
621 lnr_msg->expire = GNUNET_TIME_absolute_hton (get_block_expiration_time (copied_elements,
623 name_tmp = (char *) &lnr_msg[1];
624 memcpy (name_tmp, name, name_len);
625 rd_tmp = &name_tmp[name_len];
626 GNUNET_NAMESTORE_records_serialize (copied_elements, rd_selected, rd_ser_len, rd_tmp);
628 if (rd_selected != rd)
629 GNUNET_free_non_null (rd_selected);
631 if (NULL != zone_key)
632 lnr_msg->public_key = *zone_key;
633 if (GNUNET_YES == authoritative)
635 /* use new created signature */
636 lnr_msg->contains_sig = htons (GNUNET_YES);
637 GNUNET_assert (NULL != signature_new);
638 lnr_msg->signature = *signature_new;
639 GNUNET_free (signature_new);
641 else if (GNUNET_YES == contains_signature)
643 /* use existing signature */
644 lnr_msg->contains_sig = htons (GNUNET_YES);
645 GNUNET_assert (NULL != signature);
646 lnr_msg->signature = *signature;
648 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client,
649 &lnr_msg->gns_header.header,
651 GNUNET_free (lnr_msg);
656 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
659 * @param client GNUNET_SERVER_Client sending the message
660 * @param message message of type 'struct LookupNameMessage'
663 handle_lookup_name (void *cls,
664 struct GNUNET_SERVER_Client *client,
665 const struct GNUNET_MessageHeader *message)
667 const struct LookupNameMessage *ln_msg;
668 struct LookupNameContext lnc;
669 struct GNUNET_NAMESTORE_Client *nc;
675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676 "Received `%s' message\n",
677 "NAMESTORE_LOOKUP_NAME");
678 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
681 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
684 if (NULL == (nc = client_lookup(client)))
687 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
690 ln_msg = (const struct LookupNameMessage *) message;
691 rid = ntohl (ln_msg->gns_header.r_id);
692 name_len = ntohl (ln_msg->name_len);
693 type = ntohl (ln_msg->record_type);
694 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
697 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
700 name = (const char *) &ln_msg[1];
701 if (name[name_len -1] != '\0')
704 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
707 if (GNUNET_NAMESTORE_TYPE_ANY == type)
708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
709 "Looking up all records for name `%s' in zone `%s'\n",
711 GNUNET_short_h2s(&ln_msg->zone));
713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
714 "Looking up records with type %u for name `%s' in zone `%s'\n",
716 GNUNET_short_h2s(&ln_msg->zone));
718 /* do the actual lookup */
719 lnc.request_id = rid;
721 lnc.record_type = type;
723 lnc.zone = &ln_msg->zone;
725 GSN_database->iterate_records (GSN_database->cls,
726 &ln_msg->zone, name, 0 /* offset */,
727 &handle_lookup_name_it, &lnc))
729 /* internal error (in database plugin); might be best to just hang up on
730 plugin rather than to signal that there are 'no' results, which
731 might also be false... */
733 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
736 GNUNET_SERVER_receive_done (client, GNUNET_OK);
741 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
744 * @param client GNUNET_SERVER_Client sending the message
745 * @param message message of type 'struct RecordPutMessage'
748 handle_record_put (void *cls,
749 struct GNUNET_SERVER_Client *client,
750 const struct GNUNET_MessageHeader *message)
752 struct GNUNET_NAMESTORE_Client *nc;
753 const struct RecordPutMessage *rp_msg;
754 struct GNUNET_TIME_Absolute expire;
755 const struct GNUNET_CRYPTO_RsaSignature *signature;
756 struct RecordPutResponseMessage rpr_msg;
757 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
769 "Received `%s' message\n",
770 "NAMESTORE_RECORD_PUT");
771 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
774 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
777 if (NULL == (nc = client_lookup (client)))
780 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
783 rp_msg = (const struct RecordPutMessage *) message;
784 rid = ntohl (rp_msg->gns_header.r_id);
785 msg_size = ntohs (rp_msg->gns_header.header.size);
786 name_len = ntohs (rp_msg->name_len);
787 rd_count = ntohs (rp_msg->rd_count);
788 rd_ser_len = ntohs (rp_msg->rd_len);
789 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >= MAX_NAME_LEN) || (0 == name_len))
792 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
795 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
796 if (msg_size != msg_size_exp)
799 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
802 name = (const char *) &rp_msg[1];
803 if ('\0' != name[name_len -1])
806 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
809 expire = GNUNET_TIME_absolute_ntoh (rp_msg->expire);
810 signature = &rp_msg->signature;
811 rd_ser = &name[name_len];
813 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
816 GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd))
819 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
822 GNUNET_CRYPTO_short_hash (&rp_msg->public_key,
823 sizeof (rp_msg->public_key),
825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
826 "Putting %u records under name `%s' in zone `%s'\n",
828 GNUNET_short_h2s (&zone_hash));
829 res = GSN_database->put_records(GSN_database->cls,
835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
836 "Putting record for name `%s': %s\n",
838 (res == GNUNET_OK) ? "OK" : "FAILED");
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
841 "Sending `%s' message\n",
842 "RECORD_PUT_RESPONSE");
843 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
844 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
845 rpr_msg.gns_header.r_id = htonl (rid);
846 rpr_msg.op_result = htonl (res);
847 GNUNET_SERVER_notification_context_unicast (snc,
849 &rpr_msg.gns_header.header,
851 GNUNET_SERVER_receive_done (client, GNUNET_OK);
855 /////////////////////////////////////////////////////////////
859 * Context for record create operations passed from 'handle_record_create' to
860 * 'handle_create_record_it' as closure
862 struct CreateRecordContext
867 const struct GNUNET_NAMESTORE_RecordData *rd;
872 const struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
877 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
880 * Name for the record to create
885 * Record expiration time
887 struct GNUNET_TIME_Absolute expire;
890 * result returned from 'handle_create_record_it'
891 * GNUNET_SYSERR: failed to create the record
892 * GNUNET_NO: we updated an existing record or identical entry existed
893 * GNUNET_YES : we created a new record
900 * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
901 * in handle_record_create
903 * @param cls a 'struct CreateRecordContext *' with information about the request
904 * @param pubkey zone key of the zone
905 * @param expire expiration time
907 * @param rd_count number of records
908 * @param rd array of records
909 * @param signature signature
912 handle_create_record_it (void *cls,
913 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
914 struct GNUNET_TIME_Absolute expire,
916 unsigned int rd_count,
917 const struct GNUNET_NAMESTORE_RecordData *rd,
918 const struct GNUNET_CRYPTO_RsaSignature *signature)
920 struct CreateRecordContext *crc = cls;
921 struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
922 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
923 struct GNUNET_TIME_Absolute block_expiration;
925 int exist = GNUNET_SYSERR;
926 int update = GNUNET_NO;
928 int rd_count_new = 0;
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "Found %u existing records for `%s'\n",
932 rd_count, crc->name);
933 for (c = 0; c < rd_count; c++)
935 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) &&
936 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
938 /* Update unique PKEY */
943 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) &&
944 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
946 /* Update unique PSEU */
951 if ((crc->rd->record_type == rd[c].record_type) &&
952 (crc->rd->data_size == rd[c].data_size) &&
953 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
955 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
956 "Found existing records for `%s' to update expiration date!\n",
959 if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
960 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
961 == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
967 if (exist == GNUNET_SYSERR)
969 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970 "No existing record for name `%s'!\n",
972 rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
973 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
974 rd_count_new = rd_count + 1;
975 rd_new[rd_count] = *(crc->rd);
977 else if (update == GNUNET_NO)
979 /* Exact same record already exists */
980 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
981 "Matching record for %s' exists, no change required!\n",
989 GNUNET_assert (GNUNET_YES == update);
990 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
991 "Updating existing records for `%s'!\n",
993 rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
994 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
995 rd_count_new = rd_count;
996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
997 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
998 ? "Updating absolute expiration from %llu to %llu!\n"
999 : "Updating relative expiration from %llu to %llu!\n",
1000 rd_new[exist].expiration_time, crc->rd->expiration_time);
1001 rd_new[exist] = *(crc->rd);
1004 block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
1005 if (block_expiration.abs_value != expire.abs_value)
1006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1007 "Updated block expiration time\n");
1009 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1011 /* Database operation */
1012 GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
1013 res = GSN_database->put_records(GSN_database->cls,
1014 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
1017 rd_count_new, rd_new,
1019 GNUNET_break (GNUNET_OK == res);
1020 if (res == GNUNET_OK)
1021 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
1023 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
1027 GNUNET_free_non_null (rd_new);
1031 /* failed to create the record */
1032 crc->res = GNUNET_SYSERR;
1035 /* database operations OK */
1036 if (GNUNET_YES == update)
1038 /* we updated an existing record */
1039 crc->res = GNUNET_NO;
1043 /* we created a new record */
1044 crc->res = GNUNET_YES;
1048 /* identical entry existed, so we did nothing */
1049 crc->res = GNUNET_NO;
1054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
1059 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1062 * @param client GNUNET_SERVER_Client sending the message
1063 * @param message message of type 'struct RecordCreateMessage'
1066 handle_record_create (void *cls,
1067 struct GNUNET_SERVER_Client *client,
1068 const struct GNUNET_MessageHeader *message)
1070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1071 struct GNUNET_NAMESTORE_Client *nc;
1072 struct RecordCreateMessage *rp_msg;
1073 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1074 struct CreateRecordContext crc;
1075 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1076 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1077 struct RecordCreateResponseMessage rcr_msg;
1078 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1079 struct GNUNET_HashCode long_hash;
1082 size_t msg_size_exp;
1091 int res = GNUNET_SYSERR;
1092 crc.res = GNUNET_SYSERR;
1094 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1096 GNUNET_break_op (0);
1097 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1101 nc = client_lookup(client);
1104 GNUNET_break_op (0);
1105 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1109 rp_msg = (struct RecordCreateMessage *) message;
1110 rid = ntohl (rp_msg->gns_header.r_id);
1111 name_len = ntohs (rp_msg->name_len);
1112 msg_size = ntohs (message->size);
1113 rd_count = ntohs (rp_msg->rd_count);
1114 rd_ser_len = ntohs (rp_msg->rd_len);
1115 key_len = ntohs (rp_msg->pkey_len);
1116 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1118 if (msg_size != msg_size_exp)
1120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1121 GNUNET_break_op (0);
1122 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1126 if ((name_len == 0) || (name_len > MAX_NAME_LEN))
1128 GNUNET_break_op (0);
1129 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1133 pkey_tmp = (char *) &rp_msg[1];
1134 name_tmp = &pkey_tmp[key_len];
1135 rd_ser = &name_tmp[name_len];
1137 if (name_tmp[name_len -1] != '\0')
1139 GNUNET_break_op (0);
1140 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1144 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1146 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1147 if ((res != GNUNET_OK) || (rd_count != 1))
1149 GNUNET_break_op (0);
1152 /* Extracting and converting private key */
1153 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1154 GNUNET_assert (pkey != NULL);
1155 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1156 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1157 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1159 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash));
1163 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1164 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1165 cc->pubkey = GNUNET_malloc(sizeof (pub));
1166 memcpy (cc->pubkey, &pub, sizeof(pub));
1167 cc->zone = pubkey_hash;
1168 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1171 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1172 crc.res = GNUNET_SYSERR;
1176 crc.name = name_tmp;
1178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1180 /* Get existing records for name */
1181 res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
1182 if (res != GNUNET_SYSERR)
1184 GNUNET_CRYPTO_rsa_key_free(pkey);
1189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1190 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1191 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1192 rcr_msg.gns_header.r_id = htonl (rid);
1193 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1194 rcr_msg.op_result = htonl (GNUNET_YES);
1195 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1196 rcr_msg.op_result = htonl (GNUNET_NO);
1198 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1199 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
1201 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1206 * RemoveRecordContext
1208 * Context for record remove operations passed from 'handle_record_remove' to
1209 * 'handle_record_remove_it' as closure
1211 struct RemoveRecordContext
1216 struct GNUNET_NAMESTORE_RecordData *rd;
1219 * Zone's private keys
1221 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1230 * 1 : Could not find record to remove, empty result set
1231 * 2 : Could not find record to remove, record did not exist in result set
1232 * 3 : Could not remove records from database
1233 * 4 : Could not put records into database
1243 handle_record_remove_it (void *cls,
1244 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1245 struct GNUNET_TIME_Absolute expire,
1247 unsigned int rd_count,
1248 const struct GNUNET_NAMESTORE_RecordData *rd,
1249 const struct GNUNET_CRYPTO_RsaSignature *signature)
1251 struct RemoveRecordContext *rrc = cls;
1255 unsigned int rd_count_new;
1257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
1261 /* Could not find record to remove */
1266 /* Find record to remove */
1267 found = GNUNET_SYSERR;
1268 for (c = 0; c < rd_count; c++)
1271 if (rd[c].flags != rrc->rd->flags)
1273 if (rd[c].record_type != rrc->rd->record_type)
1276 if (rd[c].data_size != rrc->rd->data_size)
1279 if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1286 if (GNUNET_SYSERR == found)
1288 /* Could not find record to remove */
1293 if (rd_count-1 == 0)
1295 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1296 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1297 res = GSN_database->remove_records (GSN_database->cls,
1300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1301 "No records left for name `%s', removing name\n",
1303 if (GNUNET_OK != res)
1305 /* Could not remove records from database */
1313 rd_count_new = rd_count -1;
1314 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1316 unsigned int c2 = 0;
1317 for (c = 0; c < rd_count; c++)
1321 GNUNET_assert (c2 < rd_count_new);
1327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1329 /* Create dummy signature */
1330 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1331 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1335 res = GSN_database->put_records(GSN_database->cls,
1339 rd_count_new, rd_new,
1341 if (GNUNET_OK != res)
1343 /* Could not put records into database */
1353 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1356 * @param client GNUNET_SERVER_Client sending the message
1357 * @param message message of type 'struct RecordRemoveMessage'
1360 handle_record_remove (void *cls,
1361 struct GNUNET_SERVER_Client *client,
1362 const struct GNUNET_MessageHeader *message)
1364 struct GNUNET_NAMESTORE_Client *nc;
1365 const struct RecordRemoveMessage *rr_msg;
1366 struct RecordRemoveResponseMessage rrr_msg;
1367 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1368 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1369 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1370 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1371 struct GNUNET_HashCode long_hash;
1372 const char *pkey_tmp;
1373 const char *name_tmp;
1379 size_t msg_size_exp = 0;
1383 int res = GNUNET_SYSERR;
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1386 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1388 GNUNET_break_op (0);
1389 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1393 nc = client_lookup(client);
1396 GNUNET_break_op (0);
1397 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1401 rr_msg = (const struct RecordRemoveMessage *) message;
1402 rid = ntohl (rr_msg->gns_header.r_id);
1403 name_len = ntohs (rr_msg->name_len);
1404 rd_ser_len = ntohs (rr_msg->rd_len);
1405 rd_count = ntohs (rr_msg->rd_count);
1406 key_len = ntohs (rr_msg->pkey_len);
1407 msg_size = ntohs (message->size);
1409 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1411 GNUNET_break_op (0);
1412 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1416 if ((name_len >=MAX_NAME_LEN) || (name_len == 0))
1418 GNUNET_break_op (0);
1419 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1423 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1424 if (msg_size != msg_size_exp)
1426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1427 GNUNET_break_op (0);
1428 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1432 pkey_tmp = (const char *) &rr_msg[1];
1433 name_tmp = &pkey_tmp[key_len];
1434 rd_ser = &name_tmp[name_len];
1437 if ((name_len == 0) || (name_len > MAX_NAME_LEN))
1439 GNUNET_break_op (0);
1440 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1444 if (name_tmp[name_len -1] != '\0')
1446 GNUNET_break_op (0);
1447 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1451 /* Extracting and converting private key */
1452 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1453 GNUNET_assert (pkey != NULL);
1454 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1455 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1456 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1458 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1461 "Received new private key for zone `%s'\n",
1462 GNUNET_short_h2s(&pubkey_hash));
1463 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1464 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1465 cc->pubkey = GNUNET_malloc(sizeof (pub));
1466 memcpy (cc->pubkey, &pub, sizeof(pub));
1467 cc->zone = pubkey_hash;
1469 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1473 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1474 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1475 if ((res != GNUNET_OK) || (rd_count > 1))
1477 GNUNET_break_op (0);
1483 /* remove the whole name and all records */
1484 /* Database operation */
1485 res = GSN_database->remove_records (GSN_database->cls,
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1489 name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1491 if (GNUNET_OK != res)
1492 /* Could not remove entry from database */
1499 /* remove a single record */
1500 struct RemoveRecordContext rrc;
1504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1506 /* Database operation */
1507 res = GSN_database->iterate_records (GSN_database->cls,
1511 handle_record_remove_it, &rrc);
1513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1514 name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1520 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1521 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1522 rrr_msg.gns_header.r_id = htonl (rid);
1523 rrr_msg.op_result = htonl (res);
1524 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1526 GNUNET_CRYPTO_rsa_key_free (pkey);
1528 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1534 * Context for record remove operations passed from 'handle_zone_to_name' to
1535 * 'handle_zone_to_name_it' as closure
1537 struct ZoneToNameCtx
1542 struct GNUNET_NAMESTORE_Client *nc;
1552 * Zone to name iterator
1554 * @param cls struct ZoneToNameCtx *
1555 * @param zone_key the zone key
1556 * @param expire expiration date
1558 * @param rd_count number of records
1559 * @param rd record data
1560 * @param signature signature
1563 handle_zone_to_name_it (void *cls,
1564 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1565 struct GNUNET_TIME_Absolute expire,
1567 unsigned int rd_count,
1568 const struct GNUNET_NAMESTORE_RecordData *rd,
1569 const struct GNUNET_CRYPTO_RsaSignature *signature)
1571 struct ZoneToNameCtx *ztn_ctx = cls;
1572 struct ZoneToNameResponseMessage *ztnr_msg;
1573 int16_t res = GNUNET_SYSERR;
1574 uint16_t name_len = 0;
1575 uint16_t rd_ser_len = 0 ;
1576 int32_t contains_sig = 0;
1577 size_t msg_size = 0;
1579 char *rd_ser = NULL;
1584 if ((zone_key != NULL) && (name != NULL))
1587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1589 name_len = strlen (name) +1;
1593 /* no result found */
1594 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1601 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1602 rd_ser = GNUNET_malloc (rd_ser_len);
1603 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1608 if (signature != NULL)
1609 contains_sig = GNUNET_YES;
1611 contains_sig = GNUNET_NO;
1613 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1614 ztnr_msg = GNUNET_malloc (msg_size);
1616 name_tmp = (char *) &ztnr_msg[1];
1617 rd_tmp = &name_tmp[name_len];
1618 sig_tmp = &rd_tmp[rd_ser_len];
1620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1621 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1622 ztnr_msg->gns_header.header.size = htons (msg_size);
1623 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1624 ztnr_msg->res = htons (res);
1625 ztnr_msg->rd_len = htons (rd_ser_len);
1626 ztnr_msg->rd_count = htons (rd_count);
1627 ztnr_msg->name_len = htons (name_len);
1628 ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1629 if (zone_key != NULL)
1630 ztnr_msg->zone_key = *zone_key;
1632 memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1634 if ((name_len > 0) && (name != NULL))
1635 memcpy (name_tmp, name, name_len);
1637 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);
1638 if ((rd_ser_len > 0) && (rd_ser != NULL))
1639 memcpy (rd_tmp, rd_ser, rd_ser_len);
1640 if ((GNUNET_YES == contains_sig) && (signature != NULL))
1641 memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1643 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1644 GNUNET_free (ztnr_msg);
1645 GNUNET_free_non_null (rd_ser);
1650 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1653 * @param client GNUNET_SERVER_Client sending the message
1654 * @param message message of type 'struct ZoneToNameMessage'
1657 handle_zone_to_name (void *cls,
1658 struct GNUNET_SERVER_Client *client,
1659 const struct GNUNET_MessageHeader *message)
1661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1662 struct GNUNET_NAMESTORE_Client *nc;
1663 struct ZoneToNameMessage *ztn_msg;
1664 struct ZoneToNameCtx ztn_ctx;
1665 size_t msg_size = 0;
1668 if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1670 GNUNET_break_op (0);
1671 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1675 nc = client_lookup(client);
1678 GNUNET_break_op (0);
1679 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1683 ztn_msg = (struct ZoneToNameMessage *) message;
1685 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1687 GNUNET_break_op (0);
1688 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1692 rid = ntohl (ztn_msg->gns_header.r_id);
1697 struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1698 GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1701 GNUNET_short_h2s (&ztn_msg->value_zone));
1703 GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1705 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1710 * Copy record, data has to be free'd separetely
1712 * @param src source record
1713 * @param dest destination record
1716 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1718 memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1719 dest->data = GNUNET_malloc (src->data_size);
1720 memcpy ((void *) dest->data, src->data, src->data_size);
1725 * ZoneIterationProcResult
1727 * Context for record remove operations passed from
1728 * 'find_next_zone_iteration_result' to 'zone_iteraterate_proc' as closure
1730 struct ZoneIterationProcResult
1733 * The zone iteration handle
1735 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1738 * Iteration result: iteration done?
1740 int res_iteration_finished;
1743 * Iteration result: number of records included
1745 int records_included;
1748 * Iteration result: is a valid signature included?
1760 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1765 struct GNUNET_NAMESTORE_RecordData *rd;
1770 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1775 struct GNUNET_CRYPTO_RsaSignature signature;
1780 struct GNUNET_TIME_Absolute expire;
1785 * Process results for zone iteration from database
1787 * @param cls struct ZoneIterationProcResult *proc
1788 * @param zone_key the zone key
1789 * @param expire expiration time
1791 * @param rd_count number of records for this name
1792 * @param rd record data
1793 * @param signature block signature
1796 zone_iteraterate_proc (void *cls,
1797 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1798 struct GNUNET_TIME_Absolute expire,
1800 unsigned int rd_count,
1801 const struct GNUNET_NAMESTORE_RecordData *rd,
1802 const struct GNUNET_CRYPTO_RsaSignature *signature)
1804 struct ZoneIterationProcResult *proc = cls;
1805 struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1806 struct GNUNET_CRYPTO_RsaSignature *new_signature;
1807 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1808 struct GNUNET_CRYPTO_ShortHashCode hash;
1809 struct GNUNET_HashCode long_hash;
1810 struct GNUNET_TIME_Absolute e;
1811 unsigned int rd_count_filtered = 0;
1815 proc->res_iteration_finished = GNUNET_NO;
1816 proc->records_included = 0;
1818 if ((zone_key == NULL) && (name == NULL))
1820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1821 proc->res_iteration_finished = GNUNET_YES;
1825 else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1827 rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1829 for (c = 0; c < rd_count; c++)
1831 include = GNUNET_YES;
1832 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1833 c, rd[c].flags, proc->zi->must_have_flags);
1834 /* Checking must have flags */
1835 if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1838 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1843 include = GNUNET_NO;
1846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1847 c, rd[c].flags, proc->zi->must_not_have_flags);
1848 if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1851 include = GNUNET_NO;
1856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1858 if (GNUNET_YES == include)
1860 copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1861 rd_count_filtered++;
1865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1867 proc->records_included = rd_count_filtered;
1868 if (0 == rd_count_filtered)
1870 GNUNET_free (rd_filtered);
1873 proc->rd = rd_filtered;
1874 proc->name = GNUNET_strdup(name);
1875 memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1878 proc->has_signature = GNUNET_NO;
1879 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1880 GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1881 proc->zone_hash = hash;
1883 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1885 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1886 e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1888 new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1889 GNUNET_assert (signature != NULL);
1890 proc->signature = (*new_signature);
1891 GNUNET_free (new_signature);
1892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1893 name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1894 proc->has_signature = GNUNET_YES;
1896 else if (rd_count_filtered == rd_count)
1898 proc->expire = expire;
1899 if (NULL != signature)
1901 proc->signature = (*signature);
1902 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1903 name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1904 proc->has_signature = GNUNET_YES;
1908 memset (&proc->signature, '\0', sizeof (proc->signature));
1909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1919 /////////////////////////////////////////////////////////////
1923 * Find next zone iteration result in database
1925 * @param proc the zone iteration processing to use
1928 find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1930 struct GNUNET_CRYPTO_ShortHashCode *zone;
1932 if (GNUNET_YES == proc->zi->has_zone)
1933 zone = &proc->zi->zone;
1938 if (GNUNET_SYSERR ==
1939 GSN_database->iterate_records (GSN_database->cls, zone, NULL,
1941 &zone_iteraterate_proc, proc))
1948 while ((0 == proc->records_included) && (GNUNET_NO == proc->res_iteration_finished));
1953 * Send zone iteration result to client
1955 * @param proc the zone iteration processing result to send
1958 send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1960 struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1961 struct ZoneIterationResponseMessage zir_end;
1962 struct ZoneIterationResponseMessage *zir_msg;
1969 if (GNUNET_YES == proc->res_iteration_finished)
1971 if (zi->has_zone == GNUNET_YES)
1972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1973 "No more results for zone `%s'\n",
1974 GNUNET_short_h2s(&zi->zone));
1976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1977 "No more results for all zones\n");
1978 memset (&zir_end, 0, sizeof (zir_end));
1979 zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1980 zir_end.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1981 zir_end.gns_header.r_id = htonl(zi->request_id);
1982 GNUNET_SERVER_notification_context_unicast (snc,
1984 &zir_end.gns_header.header, GNUNET_NO);
1985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1986 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1990 GNUNET_assert (proc->records_included > 0);
1991 if (GNUNET_YES == zi->has_zone)
1992 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1993 "Sending name `%s' for iteration over zone `%s'\n",
1994 proc->name, GNUNET_short_h2s(&zi->zone));
1996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1997 "Sending name `%s' for iteration over all zones\n",
1999 name_len = strlen (proc->name) + 1;
2000 rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);
2001 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
2003 zir_msg = GNUNET_malloc(msg_size);
2004 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
2005 zir_msg->gns_header.header.size = htons (msg_size);
2006 zir_msg->gns_header.r_id = htonl(zi->request_id);
2007 zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire);
2008 zir_msg->reserved = htons (0);
2009 zir_msg->name_len = htons (name_len);
2010 zir_msg->rd_count = htons (proc->records_included);
2011 zir_msg->rd_len = htons (rd_ser_len);
2012 zir_msg->signature = proc->signature;
2013 zir_msg->public_key = proc->zone_key;
2014 name_tmp = (char *) &zir_msg[1];
2015 memcpy (name_tmp, proc->name, name_len);
2016 rd_ser = &name_tmp[name_len];
2017 GNUNET_NAMESTORE_records_serialize (proc->records_included, proc->rd, rd_ser_len, rd_ser);
2018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2019 "Sending `%s' message with size %u\n",
2020 "ZONE_ITERATION_RESPONSE",
2022 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client,
2023 (const struct GNUNET_MessageHeader *) zir_msg,
2025 GNUNET_free (zir_msg);
2030 * Clean up after zone iteration
2031 * @param proc the zone iteration processor
2034 clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
2038 GNUNET_free_non_null (proc->name);
2040 for (c = 0; c < proc->records_included; c++)
2041 GNUNET_free ((void *) proc->rd[c].data);
2042 GNUNET_free_non_null (proc->rd);
2044 proc->records_included = 0;
2049 * Perform the next round of the zone iteration.
2051 * @param zi zone iterator to process
2054 run_zone_iteration_round (struct GNUNET_NAMESTORE_ZoneIteration *zi)
2056 struct ZoneIterationProcResult proc;
2058 memset (&proc, 0, sizeof (proc));
2060 find_next_zone_iteration_result (&proc);
2061 if (GNUNET_YES == proc.res_iteration_finished)
2063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2064 "Zone iteration done\n");
2066 else if (0 != proc.records_included)
2068 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2069 "Zone iteration returns %u records\n",
2070 proc.records_included);
2072 send_zone_iteration_result (&proc);
2073 clean_up_zone_iteration_result (&proc);
2078 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
2081 * @param client GNUNET_SERVER_Client sending the message
2082 * @param message message of type 'struct ZoneIterationStartMessage'
2085 handle_iteration_start (void *cls,
2086 struct GNUNET_SERVER_Client *client,
2087 const struct GNUNET_MessageHeader *message)
2089 static struct GNUNET_CRYPTO_ShortHashCode zeros;
2090 const struct ZoneIterationStartMessage *zis_msg;
2091 struct GNUNET_NAMESTORE_Client *nc;
2092 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2095 nc = client_lookup (client);
2098 GNUNET_break_op (0);
2099 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2102 zis_msg = (const struct ZoneIterationStartMessage *) message;
2103 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2104 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2107 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2108 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2109 if (0 == memcmp (&zeros, &zis_msg->zone, sizeof (zeros)))
2111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2112 zi->zone = zis_msg->zone;
2113 zi->has_zone = GNUNET_NO;
2117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2118 "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2119 zi->zone = zis_msg->zone;
2120 zi->has_zone = GNUNET_YES;
2122 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2123 run_zone_iteration_round (zi);
2124 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2129 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2132 * @param client GNUNET_SERVER_Client sending the message
2133 * @param message message of type 'struct ZoneIterationStopMessage'
2136 handle_iteration_stop (void *cls,
2137 struct GNUNET_SERVER_Client *client,
2138 const struct GNUNET_MessageHeader *message)
2140 struct GNUNET_NAMESTORE_Client *nc;
2141 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2142 const struct ZoneIterationStopMessage *zis_msg;
2145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2146 "Received `%s' message\n",
2147 "ZONE_ITERATION_STOP");
2148 nc = client_lookup(client);
2152 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2155 zis_msg = (const struct ZoneIterationStopMessage *) message;
2156 rid = ntohl (zis_msg->gns_header.r_id);
2157 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2158 if (zi->request_id == rid)
2163 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2166 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2167 if (GNUNET_YES == zi->has_zone)
2168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2169 "Stopped zone iteration for zone `%s'\n",
2170 GNUNET_short_h2s (&zi->zone));
2172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2173 "Stopped zone iteration over all zones\n");
2175 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2180 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT' message
2183 * @param client GNUNET_SERVER_Client sending the message
2184 * @param message message of type 'struct ZoneIterationNextMessage'
2187 handle_iteration_next (void *cls,
2188 struct GNUNET_SERVER_Client *client,
2189 const struct GNUNET_MessageHeader *message)
2191 struct GNUNET_NAMESTORE_Client *nc;
2192 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2193 const struct ZoneIterationNextMessage *zis_msg;
2196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2197 nc = client_lookup(client);
2201 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2204 zis_msg = (const struct ZoneIterationNextMessage *) message;
2205 rid = ntohl (zis_msg->gns_header.r_id);
2206 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2207 if (zi->request_id == rid)
2212 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2215 run_zone_iteration_round (zi);
2216 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2221 * Load zone keys from directory by reading all .zkey files in this directory
2223 * @param cls int * 'counter' to store the number of files found
2224 * @param filename directory to scan
2225 * @return GNUNET_OK to continue
2228 zonekey_file_it (void *cls, const char *filename)
2230 unsigned int *counter = cls;
2231 struct GNUNET_HashCode long_hash;
2232 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2233 struct GNUNET_NAMESTORE_CryptoContainer *c;
2235 if ((NULL == filename) ||
2236 (NULL == strstr(filename, ".zkey")))
2238 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
2239 if (NULL == privkey)
2241 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2242 _("Could not parse zone key file `%s'\n"),
2246 c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
2247 c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2248 c->privkey = privkey;
2249 GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
2250 GNUNET_CRYPTO_short_hash(c->pubkey,
2251 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2254 "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
2255 GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
2256 GNUNET_assert (GNUNET_OK ==
2257 GNUNET_CONTAINER_multihashmap_put (zonekeys, &long_hash, c,
2258 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2265 * Process namestore requests.
2267 * @param cls closure
2268 * @param server the initialized server
2269 * @param cfg configuration to use
2272 run (void *cls, struct GNUNET_SERVER_Handle *server,
2273 const struct GNUNET_CONFIGURATION_Handle *cfg)
2275 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2276 {&handle_start, NULL,
2277 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2278 {&handle_lookup_name, NULL,
2279 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2280 {&handle_record_put, NULL,
2281 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2282 {&handle_record_create, NULL,
2283 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2284 {&handle_record_remove, NULL,
2285 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2286 {&handle_zone_to_name, NULL,
2287 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
2288 {&handle_iteration_start, NULL,
2289 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage) },
2290 {&handle_iteration_next, NULL,
2291 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, sizeof (struct ZoneIterationNextMessage) },
2292 {&handle_iteration_stop, NULL,
2293 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage) },
2297 unsigned int counter;
2299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2302 /* Load private keys from disk */
2304 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore",
2305 "zonefile_directory",
2306 &zonefile_directory))
2308 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2309 _("No directory to load zonefiles specified in configuration\n"));
2310 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2314 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2316 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2318 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2319 _("Creating directory `%s' for zone files failed!\n"),
2320 zonefile_directory);
2321 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2325 "Created directory `%s' for zone files\n",
2326 zonefile_directory);
2329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2330 "Scanning directory `%s' for zone files\n", zonefile_directory);
2331 zonekeys = GNUNET_CONTAINER_multihashmap_create (16);
2333 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2335 "Found %u zone files\n",
2338 /* Loading database plugin */
2340 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2344 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2345 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2346 GNUNET_free (database);
2347 if (NULL == GSN_database)
2349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2350 "Could not load database backend `%s'\n",
2352 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2356 /* Configuring server handles */
2357 GNUNET_SERVER_add_handlers (server, handlers);
2358 snc = GNUNET_SERVER_notification_context_create (server, 16);
2359 GNUNET_SERVER_disconnect_notify (server,
2360 &client_disconnect_notification,
2362 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2368 * The main function for the template service.
2370 * @param argc number of arguments from the command line
2371 * @param argv command line arguments
2372 * @return 0 ok, 1 on error
2375 main (int argc, char *const *argv)
2377 return (GNUNET_OK ==
2378 GNUNET_SERVICE_run (argc, argv, "namestore",
2379 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2382 /* end of gnunet-service-namestore.c */