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
41 struct GNUNET_NAMESTORE_ZoneIteration *next;
42 struct GNUNET_NAMESTORE_ZoneIteration *prev;
44 struct GNUNET_NAMESTORE_Client * client;
61 struct GNUNET_NAMESTORE_Client
63 struct GNUNET_NAMESTORE_Client *next;
64 struct GNUNET_NAMESTORE_Client *prev;
66 struct GNUNET_SERVER_Client * client;
68 struct GNUNET_NAMESTORE_ZoneIteration *op_head;
69 struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
72 struct GNUNET_NAMESTORE_CryptoContainer
77 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
78 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
83 * Configuration handle.
85 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
90 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
95 static char *zonefile_directory;
97 static char *db_lib_name;
101 * Our notification context.
103 static struct GNUNET_SERVER_NotificationContext *snc;
105 static struct GNUNET_NAMESTORE_Client *client_head;
106 static struct GNUNET_NAMESTORE_Client *client_tail;
108 struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
112 * Write zonefile to disk
113 * @param file where to write
116 * @return GNUNET_OK on success, GNUNET_SYSERR on fail
119 int write_key_to_file (const char *filename, struct GNUNET_NAMESTORE_CryptoContainer *c)
121 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
122 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
123 struct GNUNET_DISK_FileHandle *fd;
125 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
127 GNUNET_HashCode zone;
128 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
129 struct GNUNET_CRYPTO_RsaPrivateKey * privkey;
131 privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
134 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
135 _("File zone `%s' but corrupt content already exists, failed to write! \n"), GNUNET_h2s (&zone));
136 return GNUNET_SYSERR;
139 GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey);
140 GNUNET_CRYPTO_hash(&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
141 GNUNET_CRYPTO_rsa_key_free(privkey);
143 if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
145 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
146 _("File zone `%s' containing this key already exists\n"), GNUNET_h2s (&zone));
151 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
152 _("File zone `%s' but different zone key already exists, failed to write! \n"), GNUNET_h2s (&zone));
156 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);
161 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
163 /* must exist but not be accessible, fail for good! */
164 if (0 != ACCESS (filename, R_OK))
165 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
167 GNUNET_break (0); /* what is going on!? */
168 return GNUNET_SYSERR;
171 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
172 return GNUNET_SYSERR;
175 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
176 return GNUNET_SYSERR;
177 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
178 GNUNET_assert (enc != NULL);
179 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
181 GNUNET_DISK_file_sync (fd);
182 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
183 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
184 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 _("Stored zonekey for zone `%s' in file `%s'\n"), GNUNET_h2s(&c->zone), c->filename);
191 int zone_to_disk_it (void *cls,
192 const GNUNET_HashCode * key,
195 struct GNUNET_NAMESTORE_CryptoContainer * c = value;
197 if (c->filename != NULL)
198 write_key_to_file(c->filename, c);
201 GNUNET_asprintf(&c->filename, "%s/%s.zkey", zonefile_directory, GNUNET_h2s_full (&c->zone));
202 write_key_to_file(c->filename, c);
205 GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value);;
206 GNUNET_CRYPTO_rsa_key_free(c->privkey);
207 GNUNET_free (c->pubkey);
208 GNUNET_free(c->filename);
215 struct GNUNET_TIME_Absolute
216 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
219 struct GNUNET_TIME_Absolute expire = GNUNET_TIME_absolute_get_forever();
221 return GNUNET_TIME_absolute_get_zero();
222 for (c = 0; c < rd_count; c++)
224 if (rd[c].expiration.abs_value < expire.abs_value)
225 expire = rd[c].expiration;
231 * Task run during shutdown.
237 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
240 struct GNUNET_NAMESTORE_ZoneIteration * no;
241 struct GNUNET_NAMESTORE_ZoneIteration * tmp;
242 struct GNUNET_NAMESTORE_Client * nc;
243 struct GNUNET_NAMESTORE_Client * next;
245 GNUNET_SERVER_notification_context_destroy (snc);
248 GNUNET_CONTAINER_multihashmap_iterate(zonekeys, &zone_to_disk_it, NULL);
249 GNUNET_CONTAINER_multihashmap_destroy(zonekeys);
251 for (nc = client_head; nc != NULL; nc = next)
254 for (no = nc->op_head; no != NULL; no = tmp)
256 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
260 GNUNET_SERVER_client_drop(nc->client);
261 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
265 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
266 GNUNET_free (db_lib_name);
267 GNUNET_free_non_null(zonefile_directory);
270 static struct GNUNET_NAMESTORE_Client *
271 client_lookup (struct GNUNET_SERVER_Client *client)
273 struct GNUNET_NAMESTORE_Client * nc;
275 GNUNET_assert (NULL != client);
277 for (nc = client_head; nc != NULL; nc = nc->next)
279 if (client == nc->client)
286 * Called whenever a client is disconnected. Frees our
287 * resources associated with that client.
290 * @param client identification of the client
293 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
295 struct GNUNET_NAMESTORE_ZoneIteration * no;
296 struct GNUNET_NAMESTORE_Client * nc;
300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
302 nc = client_lookup (client);
304 if ((NULL == client) || (NULL == nc))
310 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
315 GNUNET_SERVER_client_drop(nc->client);
316 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
323 static void handle_start (void *cls,
324 struct GNUNET_SERVER_Client * client,
325 const struct GNUNET_MessageHeader * message)
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
329 struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
331 GNUNET_SERVER_notification_context_add (snc, client);
332 GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
333 GNUNET_SERVER_client_keep (client);
334 GNUNET_SERVER_receive_done (client, GNUNET_OK);
337 struct LookupNameContext
339 struct GNUNET_NAMESTORE_Client *nc;
341 uint32_t record_type;
342 GNUNET_HashCode *zone;
346 void drop_iterator (void *cls,
347 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
348 struct GNUNET_TIME_Absolute expire,
351 const struct GNUNET_NAMESTORE_RecordData *rd,
352 const struct GNUNET_CRYPTO_RsaSignature *signature)
354 GNUNET_HashCode zone_hash;
356 if (NULL != zone_key)
358 GNUNET_CRYPTO_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash);
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting zone `%s'\n", GNUNET_h2s (&zone_hash));
360 GSN_database->delete_zone (GSN_database->cls, &zone_hash);
364 (*stop) = GNUNET_YES;
370 handle_lookup_name_it (void *cls,
371 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
372 struct GNUNET_TIME_Absolute expire,
374 unsigned int rd_count,
375 const struct GNUNET_NAMESTORE_RecordData *rd,
376 const struct GNUNET_CRYPTO_RsaSignature *signature)
379 struct LookupNameContext *lnc = cls;
380 struct LookupNameResponseMessage *lnr_msg;
381 struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
382 struct GNUNET_NAMESTORE_CryptoContainer *cc;
383 struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
384 struct GNUNET_TIME_Absolute e;
385 GNUNET_HashCode zone_key_hash;
392 int copied_elements = 0;
393 int contains_signature = GNUNET_NO;
394 int authoritative = GNUNET_NO;
398 name_len = strlen(name) + 1;
400 /* count records to copy */
403 if (lnc->record_type != 0)
405 /* special record type needed */
406 for (c = 0; c < rd_count; c ++)
407 if (rd[c].record_type == lnc->record_type)
408 copied_elements++; /* found matching record */
409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
410 copied_elements, lnc->record_type, lnc->name, GNUNET_h2s(lnc->zone));
411 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
413 for (c = 0; c < rd_count; c ++)
415 if (rd[c].record_type == lnc->record_type)
417 /* found matching record */
418 memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
425 copied_elements = rd_count;
426 rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
434 expire = GNUNET_TIME_UNIT_ZERO_ABS;
437 rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
438 char rd_ser[rd_ser_len];
439 GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
441 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
442 copied_elements, lnc->name, GNUNET_h2s(lnc->zone));
444 if ((copied_elements == rd_count) && (NULL != signature))
445 contains_signature = GNUNET_YES; /* returning all records, so include signature */
447 contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
450 if ((NULL != zone_key) && (copied_elements == rd_count))
452 GNUNET_CRYPTO_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash);
453 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &zone_key_hash))
455 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &zone_key_hash);
456 e = get_block_expiration_time(rd_count, rd);
457 signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count);
458 GNUNET_assert (signature_new != NULL);
459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for name `%s' with %u records in zone `%s'\n",name, copied_elements, GNUNET_h2s(&zone_key_hash));
460 authoritative = GNUNET_YES;
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am not authoritative for name `%s' in zone `%s'\n",name, GNUNET_h2s(&zone_key_hash));
466 r_size = sizeof (struct LookupNameResponseMessage) +
467 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
471 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
472 lnr_msg = GNUNET_malloc (r_size);
473 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
474 lnr_msg->gns_header.header.size = ntohs (r_size);
475 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
476 lnr_msg->rd_count = htons (copied_elements);
477 lnr_msg->rd_len = htons (rd_ser_len);
478 lnr_msg->name_len = htons (name_len);
479 lnr_msg->expire = GNUNET_TIME_absolute_hton(get_block_expiration_time(copied_elements, rd_selected));
481 if (rd_selected != rd)
482 GNUNET_free (rd_selected);
484 if (zone_key != NULL)
485 lnr_msg->public_key = (*zone_key);
487 memset(&lnr_msg->public_key, '\0', sizeof (lnr_msg->public_key));
489 if (GNUNET_YES == authoritative)
490 { /* use new created signature */
491 lnr_msg->contains_sig = htons (GNUNET_YES);
492 GNUNET_assert (signature_new != NULL);
493 lnr_msg->signature = *signature_new;
494 GNUNET_free (signature_new);
496 else if (GNUNET_YES == contains_signature)
498 /* use existing signature */
499 lnr_msg->contains_sig = htons (GNUNET_YES);
500 GNUNET_assert (signature != NULL);
501 lnr_msg->signature = *signature;
505 /* use no signature */
506 memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature));
509 name_tmp = (char *) &lnr_msg[1];
510 rd_tmp = &name_tmp[name_len];
512 memcpy (name_tmp, name, name_len);
513 memcpy (rd_tmp, rd_ser, rd_ser_len);
515 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
516 GNUNET_free (lnr_msg);
519 static void handle_lookup_name (void *cls,
520 struct GNUNET_SERVER_Client * client,
521 const struct GNUNET_MessageHeader * message)
523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
524 struct LookupNameContext lnc;
525 struct GNUNET_NAMESTORE_Client *nc;
531 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
534 GNUNET_SERVER_receive_done (client, GNUNET_OK);
538 nc = client_lookup(client);
542 GNUNET_SERVER_receive_done (client, GNUNET_OK);
546 struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message;
547 rid = ntohl (ln_msg->gns_header.r_id);
548 name_len = ntohl (ln_msg->name_len);
549 type = ntohl (ln_msg->record_type);
551 if ((name_len == 0) || (name_len > 256))
554 GNUNET_SERVER_receive_done (client, GNUNET_OK);
558 name = (char *) &ln_msg[1];
559 if (name[name_len -1] != '\0')
562 GNUNET_SERVER_receive_done (client, GNUNET_OK);
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_h2s(&ln_msg->zone));
569 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up records with type %u for name `%s' in zone `%s'\n", type, name, GNUNET_h2s(&ln_msg->zone));
571 /* do the actual lookup */
572 lnc.request_id = rid;
574 lnc.record_type = type;
576 lnc.zone = &ln_msg->zone;
577 GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
579 GNUNET_SERVER_receive_done (client, GNUNET_OK);
582 static void handle_record_put (void *cls,
583 struct GNUNET_SERVER_Client * client,
584 const struct GNUNET_MessageHeader * message)
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
587 struct GNUNET_NAMESTORE_Client *nc;
588 struct GNUNET_TIME_Absolute expire;
589 struct GNUNET_CRYPTO_RsaSignature *signature;
590 struct RecordPutResponseMessage rpr_msg;
599 int res = GNUNET_SYSERR;
601 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
604 GNUNET_SERVER_receive_done (client, GNUNET_OK);
608 nc = client_lookup (client);
612 GNUNET_SERVER_receive_done (client, GNUNET_OK);
616 struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message;
618 rid = ntohl (rp_msg->gns_header.r_id);
619 msg_size = ntohs (rp_msg->gns_header.header.size);
620 name_len = ntohs (rp_msg->name_len);
621 rd_count = ntohs (rp_msg->rd_count);
622 rd_ser_len = ntohs(rp_msg->rd_len);
624 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
627 GNUNET_SERVER_receive_done (client, GNUNET_OK);
631 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
634 GNUNET_SERVER_receive_done (client, GNUNET_OK);
638 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
639 if (msg_size != msg_size_exp)
641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
643 GNUNET_SERVER_receive_done (client, GNUNET_OK);
646 if ((name_len == 0) || (name_len > 256))
649 GNUNET_SERVER_receive_done (client, GNUNET_OK);
653 name = (char *) &rp_msg[1];
655 if (name[name_len -1] != '\0')
658 GNUNET_SERVER_receive_done (client, GNUNET_OK);
662 expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
663 signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
665 rd_ser = &name[name_len];
666 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
667 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
668 if (res != GNUNET_OK)
674 GNUNET_HashCode zone_hash;
675 GNUNET_CRYPTO_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash);
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_h2s(&zone_hash));
679 /* Database operation */
680 res = GSN_database->put_records(GSN_database->cls,
687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
688 name, (res == GNUNET_OK) ? "OK" : "FAIL");
692 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
693 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
694 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
695 rpr_msg.gns_header.r_id = htonl (rid);
696 rpr_msg.op_result = htonl (res);
697 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
699 GNUNET_SERVER_receive_done (client, GNUNET_OK);
702 struct CreateRecordContext
704 struct GNUNET_NAMESTORE_RecordData *rd;
705 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
706 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
707 struct GNUNET_TIME_Absolute expire;
714 handle_create_record_it (void *cls,
715 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
716 struct GNUNET_TIME_Absolute expire,
718 unsigned int rd_count,
719 const struct GNUNET_NAMESTORE_RecordData *rd,
720 const struct GNUNET_CRYPTO_RsaSignature *signature)
722 struct CreateRecordContext * crc = cls;
723 struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
724 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
725 struct GNUNET_TIME_Absolute block_expiration;
727 int exist = GNUNET_SYSERR;
728 int update = GNUNET_NO;
730 int rd_count_new = 0;
732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
734 for (c = 0; c < rd_count; c++)
737 if ((crc->rd->record_type == rd[c].record_type) &&
738 (crc->rd->data_size == rd[c].data_size) &&
739 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing records for `%s' to update expiration date!\n", crc->name);
743 if (crc->rd->expiration.abs_value != rd[c].expiration.abs_value)
749 if (exist == GNUNET_SYSERR)
750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New record does not exist for name `%s'!\n", crc->name);
752 if (exist == GNUNET_SYSERR)
754 rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
755 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
756 rd_count_new = rd_count + 1;
757 rd_new[rd_count] = *(crc->rd);
759 else if (update == GNUNET_NO)
761 /* Exact same record already exists */
762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No update for %s' record required!\n", crc->name);
766 else if (update == GNUNET_YES)
769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating existing records for `%s'!\n", crc->name);
770 rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
771 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
772 rd_count_new = rd_count;
773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating expiration from %llu to %llu!\n", rd_new[exist].expiration.abs_value, crc->rd->expiration.abs_value);
774 rd_new[exist].expiration = crc->rd->expiration;
777 block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
778 if (block_expiration.abs_value != expire.abs_value)
779 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updated block expiration time\n");
781 memset (&dummy_signature, '\0', sizeof (dummy_signature));
783 /* Database operation */
784 GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
785 res = GSN_database->put_records(GSN_database->cls,
786 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
789 rd_count_new, rd_new,
791 GNUNET_break (GNUNET_OK == res);
792 if (res == GNUNET_OK)
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
799 GNUNET_free_non_null (rd_new);
803 /* failed to create the record */
804 crc->res = GNUNET_SYSERR;
807 /* database operations OK */
808 if (GNUNET_YES == update)
809 /* we updated an existing record */
810 crc->res = GNUNET_NO;
812 /* we created a new record */
813 crc->res = GNUNET_YES;
816 /* identical entry existed, so we did nothing */
817 crc->res = GNUNET_NO;
823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
827 static void handle_record_create (void *cls,
828 struct GNUNET_SERVER_Client * client,
829 const struct GNUNET_MessageHeader * message)
831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
832 struct GNUNET_NAMESTORE_Client *nc;
833 struct GNUNET_NAMESTORE_CryptoContainer *cc;
834 struct CreateRecordContext crc;
835 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
836 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
837 struct RecordCreateResponseMessage rcr_msg;
838 GNUNET_HashCode pubkey_hash;
850 int res = GNUNET_SYSERR;
851 crc.res = GNUNET_SYSERR;
853 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
856 GNUNET_SERVER_receive_done (client, GNUNET_OK);
860 nc = client_lookup(client);
864 GNUNET_SERVER_receive_done (client, GNUNET_OK);
868 struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message;
869 rid = ntohl (rp_msg->gns_header.r_id);
870 name_len = ntohs (rp_msg->name_len);
871 msg_size = ntohs (message->size);
872 rd_count = ntohs (rp_msg->rd_count);
873 rd_ser_len = ntohs (rp_msg->rd_len);
874 key_len = ntohs (rp_msg->pkey_len);
875 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
877 if (msg_size != msg_size_exp)
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
881 GNUNET_SERVER_receive_done (client, GNUNET_OK);
885 if ((name_len == 0) || (name_len > 256))
888 GNUNET_SERVER_receive_done (client, GNUNET_OK);
892 pkey_tmp = (char *) &rp_msg[1];
893 name_tmp = &pkey_tmp[key_len];
894 rd_ser = &name_tmp[name_len];
896 if (name_tmp[name_len -1] != '\0')
899 GNUNET_SERVER_receive_done (client, GNUNET_OK);
903 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
905 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
906 if ((res != GNUNET_OK) || (rd_count != 1))
912 /* Extracting and converting private key */
913 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
914 GNUNET_assert (pkey != NULL);
915 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
916 GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
918 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &pubkey_hash))
920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_h2s(&pubkey_hash));
922 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
923 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
924 cc->pubkey = GNUNET_malloc(sizeof (pub));
925 memcpy (cc->pubkey, &pub, sizeof(pub));
926 cc->zone = pubkey_hash;
928 GNUNET_CONTAINER_multihashmap_put(zonekeys, &pubkey_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
931 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
932 crc.res = GNUNET_SYSERR;
938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
940 /* Get existing records for name */
941 res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
942 if (res != GNUNET_SYSERR)
944 GNUNET_CRYPTO_rsa_key_free(pkey);
949 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
950 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
951 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
952 rcr_msg.gns_header.r_id = htonl (rid);
953 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
954 rcr_msg.op_result = htonl (GNUNET_YES);
955 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
956 rcr_msg.op_result = htonl (GNUNET_NO);
958 rcr_msg.op_result = htonl (GNUNET_SYSERR);
959 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
961 GNUNET_SERVER_receive_done (client, GNUNET_OK);
965 struct RemoveRecordContext
967 struct GNUNET_NAMESTORE_RecordData *rd;
968 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
973 handle_record_remove_it (void *cls,
974 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
975 struct GNUNET_TIME_Absolute expire,
977 unsigned int rd_count,
978 const struct GNUNET_NAMESTORE_RecordData *rd,
979 const struct GNUNET_CRYPTO_RsaSignature *signature)
981 struct RemoveRecordContext *rrc = cls;
985 unsigned int rd_count_new;
987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
991 /* Could not find record to remove */
996 /* Find record to remove */
997 found = GNUNET_SYSERR;
998 for (c = 0; c < rd_count; c++)
1000 if ((rd[c].expiration.abs_value == rrc->rd->expiration.abs_value) &&
1001 (rd[c].flags == rrc->rd->flags) &&
1002 (rd[c].record_type == rrc->rd->record_type) &&
1003 (rd[c].data_size == rrc->rd->data_size) &&
1004 (0 == memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size)))
1006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1011 if (GNUNET_SYSERR == found)
1013 /* Could not find record to remove */
1018 rd_count_new = rd_count -1;
1019 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1021 unsigned int c2 = 0;
1022 for (c = 0; c < rd_count; c++)
1026 GNUNET_assert (c2 < rd_count_new);
1032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1034 /* Create dummy signature */
1035 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1036 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1040 res = GSN_database->put_records(GSN_database->cls,
1044 rd_count_new, rd_new,
1046 if (GNUNET_OK != res)
1048 /* Could put records into database */
1056 static void handle_record_remove (void *cls,
1057 struct GNUNET_SERVER_Client * client,
1058 const struct GNUNET_MessageHeader * message)
1060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1061 struct GNUNET_NAMESTORE_Client *nc;
1062 struct RecordRemoveResponseMessage rrr_msg;
1063 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1064 struct GNUNET_NAMESTORE_CryptoContainer *cc = NULL;
1065 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1066 GNUNET_HashCode pubkey_hash;
1067 char * pkey_tmp = NULL;
1068 char * name_tmp = NULL;
1069 char * rd_ser = NULL;
1071 size_t name_len = 0;
1072 size_t rd_ser_len = 0;
1073 size_t msg_size = 0;
1074 size_t msg_size_exp = 0;
1078 int res = GNUNET_SYSERR;
1080 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1082 GNUNET_break_op (0);
1083 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1087 nc = client_lookup(client);
1090 GNUNET_break_op (0);
1091 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1095 struct RecordRemoveMessage * rr_msg = (struct RecordRemoveMessage *) message;
1096 rid = ntohl (rr_msg->gns_header.r_id);
1097 name_len = ntohs (rr_msg->name_len);
1098 rd_ser_len = ntohs (rr_msg->rd_len);
1099 rd_count = ntohs (rr_msg->rd_count);
1100 key_len = ntohs (rr_msg->pkey_len);
1101 msg_size = ntohs (message->size);
1103 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1105 GNUNET_break_op (0);
1106 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1110 if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
1112 GNUNET_break_op (0);
1113 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1117 msg_size_exp = sizeof (struct RecordRemoveMessage) + 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 ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
1128 GNUNET_break_op (0);
1129 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1133 pkey_tmp = (char *) &rr_msg[1];
1134 name_tmp = &pkey_tmp[key_len];
1135 rd_ser = &name_tmp[name_len];
1138 if ((name_len == 0) || (name_len > 256))
1140 GNUNET_break_op (0);
1141 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1145 if (name_tmp[name_len -1] != '\0')
1147 GNUNET_break_op (0);
1148 GNUNET_SERVER_receive_done (client, GNUNET_OK);
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_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1158 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &pubkey_hash))
1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_h2s(&pubkey_hash));
1161 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1162 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1163 cc->pubkey = GNUNET_malloc(sizeof (pub));
1164 memcpy (cc->pubkey, &pub, sizeof(pub));
1165 cc->zone = pubkey_hash;
1167 GNUNET_CONTAINER_multihashmap_put(zonekeys, &pubkey_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1170 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1171 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1172 if ((res != GNUNET_OK) || (rd_count != 1))
1174 GNUNET_break_op (0);
1178 struct RemoveRecordContext rrc;
1182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
1184 /* Database operation */
1185 res = GSN_database->iterate_records (GSN_database->cls,
1189 handle_record_remove_it, &rrc);
1191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1192 name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1198 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1199 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1200 rrr_msg.gns_header.r_id = htonl (rid);
1201 rrr_msg.op_result = htonl (res);
1202 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1204 GNUNET_CRYPTO_rsa_key_free (pkey);
1206 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1210 struct ZoneToNameCtx
1212 struct GNUNET_NAMESTORE_Client *nc;
1217 handle_zone_to_name_it (void *cls,
1218 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1219 struct GNUNET_TIME_Absolute expire,
1221 unsigned int rd_count,
1222 const struct GNUNET_NAMESTORE_RecordData *rd,
1223 const struct GNUNET_CRYPTO_RsaSignature *signature)
1225 struct ZoneToNameCtx * ztn_ctx = cls;
1226 struct ZoneToNameResponseMessage *ztnr_msg;
1227 int16_t res = GNUNET_SYSERR;
1228 uint16_t name_len = 0;
1229 uint16_t rd_ser_len = 0 ;
1230 int32_t contains_sig = 0;
1231 size_t msg_size = 0;
1233 char *rd_ser = NULL;
1238 if ((zone_key != NULL) && (name != NULL))
1241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1243 name_len = strlen (name) +1;
1247 /* no result found */
1248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1255 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1256 rd_ser = GNUNET_malloc (rd_ser_len);
1257 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1262 if (signature != NULL)
1263 contains_sig = GNUNET_YES;
1265 contains_sig = GNUNET_NO;
1269 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1270 ztnr_msg = GNUNET_malloc (msg_size);
1272 name_tmp = (char *) &ztnr_msg[1];
1273 rd_tmp = &name_tmp[name_len];
1274 sig_tmp = &rd_tmp[rd_ser_len];
1276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1277 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1278 ztnr_msg->gns_header.header.size = htons (msg_size);
1279 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1280 ztnr_msg->res = htons (res);
1281 ztnr_msg->rd_len = htons (rd_ser_len);
1282 ztnr_msg->rd_count = htons (rd_count);
1283 ztnr_msg->name_len = htons (name_len);
1284 ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1285 if (zone_key != NULL)
1286 ztnr_msg->zone_key = *zone_key;
1288 memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1290 if ((name_len > 0) && (name != NULL))
1291 memcpy (name_tmp, name, name_len);
1293 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);
1294 if ((rd_ser_len > 0) && (rd_ser != NULL))
1295 memcpy (rd_tmp, rd_ser, rd_ser_len);
1296 if ((GNUNET_YES == contains_sig) && (signature != NULL))
1297 memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1299 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1300 GNUNET_free (ztnr_msg);
1301 GNUNET_free_non_null (rd_ser);
1305 static void handle_zone_to_name (void *cls,
1306 struct GNUNET_SERVER_Client * client,
1307 const struct GNUNET_MessageHeader * message)
1309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1310 struct GNUNET_NAMESTORE_Client *nc;
1311 struct ZoneToNameCtx ztn_ctx;
1312 size_t msg_size = 0;
1315 if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1317 GNUNET_break_op (0);
1318 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1322 nc = client_lookup(client);
1325 GNUNET_break_op (0);
1326 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1330 struct ZoneToNameMessage *ztn_msg = (struct ZoneToNameMessage *) message;
1332 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1334 GNUNET_break_op (0);
1335 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1339 rid = ntohl (ztn_msg->gns_header.r_id);
1344 char * z_tmp = strdup (GNUNET_h2s (&ztn_msg->zone));
1345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1347 GNUNET_h2s (&ztn_msg->value_zone));
1348 GNUNET_free (z_tmp);
1350 GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1352 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1355 struct ZoneIterationProcResult
1358 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1361 struct GNUNET_CRYPTO_RsaSignature signature;
1362 struct GNUNET_TIME_Absolute expire;
1372 void zone_iteration_proc (void *cls,
1373 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1374 struct GNUNET_TIME_Absolute expire,
1376 unsigned int rd_count,
1377 const struct GNUNET_NAMESTORE_RecordData *rd,
1378 const struct GNUNET_CRYPTO_RsaSignature *signature)
1380 struct GNUNET_NAMESTORE_ZoneIteration *zi = cls;
1381 struct GNUNET_NAMESTORE_Client *nc = zi->client;
1382 struct GNUNET_NAMESTORE_CryptoContainer * cc;
1383 struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
1384 struct GNUNET_TIME_Absolute e;
1385 GNUNET_HashCode zone_key_hash;
1386 int authoritative = GNUNET_NO;
1388 if ((zone_key == NULL) && (name == NULL))
1390 struct ZoneIterationResponseMessage zir_msg;
1391 if (zi->has_zone == GNUNET_YES)
1392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_h2s(&zi->zone));
1394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n");
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE");
1397 zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1398 zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1399 zir_msg.gns_header.r_id = htonl(zi->request_id);
1400 zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_absolute_get_zero());
1401 zir_msg.name_len = htons (0);
1402 zir_msg.reserved = htons (0);
1403 zir_msg.rd_count = htons (0);
1404 zir_msg.rd_len = htons (0);
1405 memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key));
1406 memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature));
1407 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1410 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
1416 struct ZoneIterationResponseMessage *zir_msg;
1417 if (zi->has_zone == GNUNET_YES)
1418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n",
1419 name, GNUNET_h2s(&zi->zone));
1420 if (zi->has_zone == GNUNET_NO)
1421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n",
1429 name_len = strlen (name) +1;
1431 rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1432 char rd_ser[rd_ser_len];
1433 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1434 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1435 zir_msg = GNUNET_malloc(msg_size);
1437 name_tmp = (char *) &zir_msg[1];
1438 rd_tmp = &name_tmp[name_len];
1440 GNUNET_CRYPTO_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash);
1441 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &zone_key_hash))
1443 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &zone_key_hash);
1444 e = get_block_expiration_time(rd_count, rd);
1446 signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count);
1447 GNUNET_assert (signature_new != NULL);
1448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n", name, GNUNET_h2s(&zone_key_hash), rd_count, e.abs_value);
1449 authoritative = GNUNET_YES;
1453 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1454 zir_msg->gns_header.header.size = htons (msg_size);
1455 zir_msg->gns_header.r_id = htonl(zi->request_id);
1456 zir_msg->expire = GNUNET_TIME_absolute_hton(expire);
1457 zir_msg->reserved = htons (0);
1458 zir_msg->name_len = htons (name_len);
1459 zir_msg->rd_count = htons (rd_count);
1460 zir_msg->rd_len = htons (rd_ser_len);
1461 if ((GNUNET_YES == authoritative) && (NULL != signature_new))
1463 zir_msg->signature = *signature_new;
1464 GNUNET_free (signature_new);
1467 zir_msg->signature = *signature;
1468 GNUNET_assert (NULL != zone_key);
1469 if (zone_key != NULL)
1470 zir_msg->public_key = *zone_key;
1471 memcpy (name_tmp, name, name_len);
1472 memcpy (rd_tmp, rd_ser, rd_ser_len);
1474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size);
1475 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) zir_msg, GNUNET_NO);
1476 GNUNET_free (zir_msg);
1480 static void handle_iteration_start (void *cls,
1481 struct GNUNET_SERVER_Client * client,
1482 const struct GNUNET_MessageHeader * message)
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
1486 struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message;
1487 struct GNUNET_NAMESTORE_Client *nc;
1488 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1490 nc = client_lookup(client);
1493 GNUNET_break_op (0);
1494 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1498 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
1499 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1502 zi->zone = zis_msg->zone;
1504 GNUNET_HashCode dummy;
1505 GNUNET_HashCode *zone_tmp;
1506 memset (&dummy, '\0', sizeof (dummy));
1507 if (0 == memcmp (&dummy, &zis_msg->zone, sizeof (dummy)))
1509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
1510 zi->has_zone = GNUNET_NO;
1515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over zone `%s'\n", GNUNET_h2s (&zis_msg->zone));
1516 zi->has_zone = GNUNET_YES;
1517 zone_tmp = &zis_msg->zone;
1520 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1522 GSN_database->iterate_records (GSN_database->cls, zone_tmp , NULL, zi->offset , &zone_iteration_proc, zi);
1523 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1526 static void handle_iteration_stop (void *cls,
1527 struct GNUNET_SERVER_Client * client,
1528 const struct GNUNET_MessageHeader * message)
1530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1532 struct GNUNET_NAMESTORE_Client *nc;
1533 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1534 struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1537 nc = client_lookup(client);
1540 GNUNET_break_op (0);
1541 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1545 rid = ntohl (zis_msg->gns_header.r_id);
1546 for (zi = nc->op_head; zi != NULL; zi = zi->next)
1548 if (zi->request_id == rid)
1553 GNUNET_break_op (0);
1554 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1558 GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1559 if (GNUNET_YES == zi->has_zone)
1560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone));
1562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration all zones\n");
1565 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1568 static void handle_iteration_next (void *cls,
1569 struct GNUNET_SERVER_Client * client,
1570 const struct GNUNET_MessageHeader * message)
1572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1574 struct GNUNET_NAMESTORE_Client *nc;
1575 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1576 GNUNET_HashCode *zone_tmp;
1577 struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1580 nc = client_lookup(client);
1583 GNUNET_break_op (0);
1584 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1588 rid = ntohl (zis_msg->gns_header.r_id);
1589 for (zi = nc->op_head; zi != NULL; zi = zi->next)
1591 if (zi->request_id == rid)
1596 GNUNET_break_op (0);
1597 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1601 if (GNUNET_YES == zi->has_zone)
1602 zone_tmp = &zi->zone;
1607 GSN_database->iterate_records (GSN_database->cls, zone_tmp, NULL, zi->offset , &zone_iteration_proc, zi);
1608 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1611 int zonekey_file_it (void *cls, const char *filename)
1614 if ((filename != NULL) && (NULL != strstr(filename, ".zkey")))
1616 struct GNUNET_CRYPTO_RsaPrivateKey * privkey;
1617 struct GNUNET_NAMESTORE_CryptoContainer *c;
1618 privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
1619 if (privkey == NULL)
1622 c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1623 c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1624 c->privkey = privkey;
1625 GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
1626 GNUNET_CRYPTO_hash(c->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &c->zone);
1628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found zonefile for zone `%s'\n", GNUNET_h2s (&c->zone));
1630 GNUNET_CONTAINER_multihashmap_put(zonekeys, &c->zone, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1638 * Process template requests.
1640 * @param cls closure
1641 * @param server the initialized server
1642 * @param cfg configuration to use
1645 run (void *cls, struct GNUNET_SERVER_Handle *server,
1646 const struct GNUNET_CONFIGURATION_Handle *cfg)
1650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1652 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1653 {&handle_start, NULL,
1654 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
1655 {&handle_lookup_name, NULL,
1656 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
1657 {&handle_record_put, NULL,
1658 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
1659 {&handle_record_create, NULL,
1660 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
1661 {&handle_record_remove, NULL,
1662 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
1663 {&handle_zone_to_name, NULL,
1664 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
1665 {&handle_iteration_start, NULL,
1666 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
1667 {&handle_iteration_next, NULL,
1668 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
1669 {&handle_iteration_stop, NULL,
1670 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0},
1676 /* Load private keys from disk */
1678 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", "zonefile_directory",
1679 &zonefile_directory))
1681 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No directory to load zonefiles specified in configuration\n"));
1682 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1686 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
1688 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
1690 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Creating directory `%s' for zone files failed!\n"), zonefile_directory);
1691 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created directory `%s' for zone files\n", zonefile_directory);
1697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scanning directory `%s' for zone files\n", zonefile_directory);
1698 zonekeys = GNUNET_CONTAINER_multihashmap_create (10);
1699 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
1700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u zone files\n", counter);
1702 /* Loading database plugin */
1704 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
1706 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1708 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1709 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1710 GNUNET_free (database);
1711 if (GSN_database == NULL)
1713 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
1715 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1719 /* Configuring server handles */
1720 GNUNET_SERVER_add_handlers (server, handlers);
1721 snc = GNUNET_SERVER_notification_context_create (server, 16);
1722 GNUNET_SERVER_disconnect_notify (server,
1723 &client_disconnect_notification,
1726 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1733 * The main function for the template service.
1735 * @param argc number of arguments from the command line
1736 * @param argv command line arguments
1737 * @return 0 ok, 1 on error
1740 main (int argc, char *const *argv)
1742 return (GNUNET_OK ==
1743 GNUNET_SERVICE_run (argc, argv, "namestore",
1744 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1747 /* end of gnunet-service-namestore.c */