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"
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;
57 struct GNUNET_NAMESTORE_Client
59 struct GNUNET_NAMESTORE_Client *next;
60 struct GNUNET_NAMESTORE_Client *prev;
62 struct GNUNET_SERVER_Client * client;
64 struct GNUNET_NAMESTORE_ZoneIteration *op_head;
65 struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
71 * Configuration handle.
73 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
75 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
78 * Our notification context.
80 static struct GNUNET_SERVER_NotificationContext *snc;
82 static char *db_lib_name;
84 static struct GNUNET_NAMESTORE_Client *client_head;
85 static struct GNUNET_NAMESTORE_Client *client_tail;
89 * Task run during shutdown.
95 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
97 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
99 struct GNUNET_NAMESTORE_ZoneIteration * no;
100 struct GNUNET_NAMESTORE_ZoneIteration * tmp;
101 struct GNUNET_NAMESTORE_Client * nc;
102 struct GNUNET_NAMESTORE_Client * next;
104 GNUNET_SERVER_notification_context_destroy (snc);
107 for (nc = client_head; nc != NULL; nc = next)
110 for (no = nc->op_head; no != NULL; no = tmp)
113 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
117 GNUNET_SERVER_client_drop(nc->client);
118 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
122 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
123 GNUNET_free (db_lib_name);
126 static struct GNUNET_NAMESTORE_Client *
127 client_lookup (struct GNUNET_SERVER_Client *client)
129 struct GNUNET_NAMESTORE_Client * nc;
131 GNUNET_assert (NULL != client);
133 for (nc = client_head; nc != NULL; nc = nc->next)
135 if (client == nc->client)
142 * Called whenever a client is disconnected. Frees our
143 * resources associated with that client.
146 * @param client identification of the client
149 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
151 struct GNUNET_NAMESTORE_ZoneIteration * no;
152 struct GNUNET_NAMESTORE_Client * nc;
156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
158 nc = client_lookup (client);
160 if ((NULL == client) || (NULL == nc))
163 for (no = nc->op_head; no != NULL; no = no->next)
165 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
169 GNUNET_SERVER_client_drop(nc->client);
170 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
176 static void handle_start (void *cls,
177 struct GNUNET_SERVER_Client * client,
178 const struct GNUNET_MessageHeader * message)
180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
182 struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
184 GNUNET_SERVER_notification_context_add (snc, client);
185 GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
186 GNUNET_SERVER_client_keep (client);
187 GNUNET_SERVER_receive_done (client, GNUNET_OK);
190 struct LookupNameContext
192 struct GNUNET_NAMESTORE_Client *nc;
194 uint32_t record_type;
195 GNUNET_HashCode *zone;
199 void drop_iterator (void *cls,
200 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
201 struct GNUNET_TIME_Absolute expire,
204 const struct GNUNET_NAMESTORE_RecordData *rd,
205 const struct GNUNET_CRYPTO_RsaSignature *signature)
207 GNUNET_HashCode zone_hash;
209 if (NULL != zone_key)
211 GNUNET_CRYPTO_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash);
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting zone `%s'\n", GNUNET_h2s (&zone_hash));
213 GSN_database->delete_zone (GSN_database->cls, &zone_hash);
217 (*stop) = GNUNET_YES;
223 handle_lookup_name_it (void *cls,
224 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
225 struct GNUNET_TIME_Absolute expire,
227 unsigned int rd_count,
228 const struct GNUNET_NAMESTORE_RecordData *rd,
229 const struct GNUNET_CRYPTO_RsaSignature *signature)
232 struct LookupNameContext *lnc = cls;
233 struct LookupNameResponseMessage *lnr_msg;
234 struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
241 int copied_elements = 0;
242 int contains_signature = 0;
246 name_len = strlen(name) + 1;
248 /* count records to copy */
251 if (lnc->record_type != 0)
253 /* special record type needed */
254 for (c = 0; c < rd_count; c ++)
255 if (rd[c].record_type == lnc->record_type)
256 copied_elements++; /* found matching record */
257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
258 copied_elements, lnc->record_type, lnc->name, GNUNET_h2s(lnc->zone));
259 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
261 for (c = 0; c < rd_count; c ++)
263 if (rd[c].record_type == lnc->record_type)
265 /* found matching record */
266 memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
273 copied_elements = rd_count;
274 rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
282 expire = GNUNET_TIME_UNIT_ZERO_ABS;
285 rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
286 char rd_ser[rd_ser_len];
287 GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
289 if (rd_selected != rd)
290 GNUNET_free (rd_selected);
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
293 copied_elements, lnc->name, GNUNET_h2s(lnc->zone));
295 if ((copied_elements == rd_count) && (signature != NULL))
296 contains_signature = GNUNET_YES;
298 contains_signature = GNUNET_NO;
300 r_size = sizeof (struct LookupNameResponseMessage) +
301 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
306 lnr_msg = GNUNET_malloc (r_size);
307 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
308 lnr_msg->gns_header.header.size = ntohs (r_size);
309 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
310 lnr_msg->rd_count = htons (copied_elements);
311 lnr_msg->rd_len = htons (rd_ser_len);
312 lnr_msg->name_len = htons (name_len);
313 lnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
314 lnr_msg->public_key = (*zone_key);
315 lnr_msg->contains_sig = htons (contains_signature);
316 if (GNUNET_YES == contains_signature)
317 lnr_msg->signature = *signature;
319 memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature));
321 name_tmp = (char *) &lnr_msg[1];
322 rd_tmp = &name_tmp[name_len];
324 memcpy (name_tmp, name, name_len);
325 memcpy (rd_tmp, rd_ser, rd_ser_len);
327 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
329 GNUNET_free (lnr_msg);
332 static void handle_lookup_name (void *cls,
333 struct GNUNET_SERVER_Client * client,
334 const struct GNUNET_MessageHeader * message)
336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
337 struct LookupNameContext lnc;
338 struct GNUNET_NAMESTORE_Client *nc;
345 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
348 GNUNET_SERVER_receive_done (client, GNUNET_OK);
352 nc = client_lookup(client);
356 GNUNET_SERVER_receive_done (client, GNUNET_OK);
360 struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message;
361 rid = ntohl (ln_msg->gns_header.r_id);
362 name_len = ntohl (ln_msg->name_len);
363 type = ntohl (ln_msg->record_type);
365 if ((name_len == 0) || (name_len > 256))
368 GNUNET_SERVER_receive_done (client, GNUNET_OK);
372 name = (char *) &ln_msg[1];
373 if (name[name_len -1] != '\0')
376 GNUNET_SERVER_receive_done (client, GNUNET_OK);
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_h2s(&ln_msg->zone));
383 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));
385 /* do the actual lookup */
386 lnc.request_id = rid;
388 lnc.record_type = type;
390 lnc.zone = &ln_msg->zone;
391 res = GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
393 GNUNET_SERVER_receive_done (client, GNUNET_OK);
396 static void handle_record_put (void *cls,
397 struct GNUNET_SERVER_Client * client,
398 const struct GNUNET_MessageHeader * message)
400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
401 struct GNUNET_NAMESTORE_Client *nc;
402 struct GNUNET_TIME_Absolute expire;
403 struct GNUNET_CRYPTO_RsaSignature *signature;
404 struct RecordPutResponseMessage rpr_msg;
413 int res = GNUNET_SYSERR;
415 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
418 GNUNET_SERVER_receive_done (client, GNUNET_OK);
422 nc = client_lookup (client);
426 GNUNET_SERVER_receive_done (client, GNUNET_OK);
430 struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message;
432 rid = ntohl (rp_msg->gns_header.r_id);
433 msg_size = ntohs (rp_msg->gns_header.header.size);
434 name_len = ntohs (rp_msg->name_len);
435 rd_count = ntohs (rp_msg->rd_count);
436 rd_ser_len = ntohs(rp_msg->rd_len);
438 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
441 GNUNET_SERVER_receive_done (client, GNUNET_OK);
445 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
448 GNUNET_SERVER_receive_done (client, GNUNET_OK);
452 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
453 if (msg_size != msg_size_exp)
455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
457 GNUNET_SERVER_receive_done (client, GNUNET_OK);
460 if ((name_len == 0) || (name_len > 256))
463 GNUNET_SERVER_receive_done (client, GNUNET_OK);
467 name = (char *) &rp_msg[1];
469 if (name[name_len -1] != '\0')
472 GNUNET_SERVER_receive_done (client, GNUNET_OK);
476 expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
477 signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
479 rd_ser = &name[name_len];
480 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
481 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
482 if (res != GNUNET_OK)
488 GNUNET_HashCode zone_hash;
489 GNUNET_CRYPTO_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash);
491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_h2s(&zone_hash));
493 /* Database operation */
494 res = GSN_database->put_records(GSN_database->cls,
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
502 name, (res == GNUNET_OK) ? "OK" : "FAIL");
506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
507 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
508 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
509 rpr_msg.gns_header.r_id = rp_msg->gns_header.r_id;
510 rpr_msg.op_result = htons (res);
511 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
513 GNUNET_SERVER_receive_done (client, GNUNET_OK);
516 struct CreateRecordContext
518 struct GNUNET_NAMESTORE_RecordData *rd;
519 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
520 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
521 struct GNUNET_TIME_Absolute expire;
528 handle_create_record_it (void *cls,
529 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
530 struct GNUNET_TIME_Absolute expire,
532 unsigned int rd_count,
533 const struct GNUNET_NAMESTORE_RecordData *rd,
534 const struct GNUNET_CRYPTO_RsaSignature *signature)
536 struct CreateRecordContext * crc = cls;
537 struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
538 struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
540 int exist = GNUNET_SYSERR;
541 int update = GNUNET_NO;
543 int rd_count_new = 0;
545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
547 for (c = 0; c < rd_count; c++)
550 if ((crc->rd->record_type == rd[c].record_type) &&
551 (crc->rd->data_size == rd[c].data_size) &&
552 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing records for `%s' to update expiration date!\n", crc->name);
556 if (crc->rd->expiration.abs_value != rd[c].expiration.abs_value)
562 if (exist == GNUNET_SYSERR)
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "NO existing records for `%s' to update!\n", crc->name);
565 if (exist == GNUNET_SYSERR)
567 rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
568 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
569 rd_count_new = rd_count + 1;
570 rd_new[rd_count] = *(crc->rd);
571 signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count+1);
573 if (NULL == signature_new)
580 else if (update == GNUNET_NO)
582 /* Exact same record already exists */
583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No update for %s' record required!\n", crc->name);
587 else if (update == GNUNET_YES)
590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating existing records for `%s'!\n", crc->name);
591 rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
592 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
593 rd_count_new = rd_count;
594 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating expiration from %llu to %llu!\n", rd_new[exist].expiration.abs_value, crc->rd->expiration.abs_value);
595 rd_new[exist].expiration = crc->rd->expiration;
596 signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count_new);
597 if (NULL == signature_new)
605 /* Database operation */
606 GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
607 res = GSN_database->put_records(GSN_database->cls,
608 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
611 rd_count_new, rd_new,
613 GNUNET_break (GNUNET_OK == res);
617 GNUNET_free_non_null (rd_new);
618 GNUNET_free_non_null (signature_new);
622 /* failed to create the record */
623 crc->res = GNUNET_SYSERR;
626 /* database operations OK */
627 if (GNUNET_YES == update)
628 /* we updated an existing record */
629 crc->res = GNUNET_NO;
631 /* we created a new record */
632 crc->res = GNUNET_YES;
635 /* identical entry existed, so we did nothing */
636 crc->res = GNUNET_NO;
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
646 static void handle_record_create (void *cls,
647 struct GNUNET_SERVER_Client * client,
648 const struct GNUNET_MessageHeader * message)
650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
651 struct GNUNET_NAMESTORE_Client *nc;
652 struct CreateRecordContext crc;
653 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
654 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
655 struct RecordCreateResponseMessage rcr_msg;
656 GNUNET_HashCode pubkey_hash;
668 int res = GNUNET_SYSERR;
670 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
673 GNUNET_SERVER_receive_done (client, GNUNET_OK);
677 nc = client_lookup(client);
681 GNUNET_SERVER_receive_done (client, GNUNET_OK);
685 struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message;
686 rid = ntohl (rp_msg->gns_header.r_id);
687 name_len = ntohs (rp_msg->name_len);
688 msg_size = ntohs (message->size);
689 rd_count = ntohs (rp_msg->rd_count);
690 rd_ser_len = ntohs (rp_msg->rd_len);
691 key_len = ntohs (rp_msg->pkey_len);
692 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
694 if (msg_size != msg_size_exp)
696 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
698 GNUNET_SERVER_receive_done (client, GNUNET_OK);
702 if ((name_len == 0) || (name_len > 256))
705 GNUNET_SERVER_receive_done (client, GNUNET_OK);
709 pkey_tmp = (char *) &rp_msg[1];
710 name_tmp = &pkey_tmp[key_len];
711 rd_ser = &name_tmp[name_len];
713 if (name_tmp[name_len -1] != '\0')
716 GNUNET_SERVER_receive_done (client, GNUNET_OK);
720 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
721 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
722 if ((res != GNUNET_OK) || (rd_count != 1))
728 /* Extracting and converting private key */
729 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
730 GNUNET_assert (pkey != NULL);
731 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
732 GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
741 /* Get existing records for name */
742 res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
743 if (res != GNUNET_SYSERR)
745 GNUNET_CRYPTO_rsa_key_free(pkey);
749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
750 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
751 rcr_msg.gns_header.r_id = htonl (rid);
752 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
753 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
754 rcr_msg.op_result = htons (GNUNET_YES);
755 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
756 rcr_msg.op_result = htons (GNUNET_NO);
758 rcr_msg.op_result = htons (GNUNET_SYSERR);
759 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
761 GNUNET_SERVER_receive_done (client, GNUNET_OK);
765 struct RemoveRecordContext
767 struct GNUNET_NAMESTORE_RecordData *rd;
768 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
773 handle_record_remove_it (void *cls,
774 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
775 struct GNUNET_TIME_Absolute expire,
777 unsigned int rd_count,
778 const struct GNUNET_NAMESTORE_RecordData *rd,
779 const struct GNUNET_CRYPTO_RsaSignature *signature)
781 struct RemoveRecordContext *rrc = cls;
782 unsigned int rd_count_new = rd_count -1;
783 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
786 int found = GNUNET_NO;
788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
792 /* Could not find record to remove */
797 /* Find record to remove */
799 for (c = 0; c < rd_count; c++)
801 if ((rd[c].expiration.abs_value == rrc->rd->expiration.abs_value) &&
802 (rd[c].flags == rrc->rd->flags) &&
803 (rd[c].record_type == rrc->rd->record_type) &&
804 (rd[c].data_size == rrc->rd->data_size) &&
805 (0 == memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size)))
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
817 if ((c2 != rd_count_new) || (found == GNUNET_NO))
819 /* Could not find record to remove */
823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
825 /* Create new signature */
826 struct GNUNET_CRYPTO_RsaSignature * new_signature;
827 new_signature = GNUNET_NAMESTORE_create_signature (rrc->pkey, name, rd_new, rd_count_new);
829 if (new_signature == NULL)
831 /* Signature failed */
837 res = GSN_database->put_records(GSN_database->cls,
841 rd_count_new, rd_new,
843 GNUNET_free (new_signature);
845 if (GNUNET_OK != res)
847 /* Could put records into database */
855 static void handle_record_remove (void *cls,
856 struct GNUNET_SERVER_Client * client,
857 const struct GNUNET_MessageHeader * message)
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
860 struct GNUNET_NAMESTORE_Client *nc;
861 struct RecordRemoveResponseMessage rrr_msg;
862 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
863 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
864 GNUNET_HashCode pubkey_hash;
865 char * pkey_tmp = NULL;
866 char * name_tmp = NULL;
867 char * rd_ser = NULL;
870 size_t rd_ser_len = 0;
872 size_t msg_size_exp = 0;
876 int res = GNUNET_SYSERR;
878 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
881 GNUNET_SERVER_receive_done (client, GNUNET_OK);
885 nc = client_lookup(client);
889 GNUNET_SERVER_receive_done (client, GNUNET_OK);
893 struct RecordRemoveMessage * rr_msg = (struct RecordRemoveMessage *) message;
894 rid = ntohl (rr_msg->gns_header.r_id);
895 name_len = ntohs (rr_msg->name_len);
896 rd_ser_len = ntohs (rr_msg->rd_len);
897 rd_count = ntohs (rr_msg->rd_count);
898 key_len = ntohs (rr_msg->pkey_len);
899 msg_size = ntohs (message->size);
901 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
904 GNUNET_SERVER_receive_done (client, GNUNET_OK);
908 if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
911 GNUNET_SERVER_receive_done (client, GNUNET_OK);
915 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
916 if (msg_size != msg_size_exp)
918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
920 GNUNET_SERVER_receive_done (client, GNUNET_OK);
924 if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
927 GNUNET_SERVER_receive_done (client, GNUNET_OK);
931 pkey_tmp = (char *) &rr_msg[1];
932 name_tmp = &pkey_tmp[key_len];
933 rd_ser = &name_tmp[name_len];
936 if ((name_len == 0) || (name_len > 256))
939 GNUNET_SERVER_receive_done (client, GNUNET_OK);
943 if (name_tmp[name_len -1] != '\0')
946 GNUNET_SERVER_receive_done (client, GNUNET_OK);
950 /* Extracting and converting private key */
951 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
952 GNUNET_assert (pkey != NULL);
953 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
954 GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
956 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
957 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
958 if ((res != GNUNET_OK) || (rd_count != 1))
964 struct RemoveRecordContext rrc;
968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
970 /* Database operation */
971 res = GSN_database->iterate_records (GSN_database->cls,
975 handle_record_remove_it, &rrc);
977 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
978 name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
984 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
985 rrr_msg.gns_header.r_id = rr_msg->gns_header.r_id;
986 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
987 rrr_msg.op_result = htons (res);
988 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
990 GNUNET_CRYPTO_rsa_key_free (pkey);
992 GNUNET_SERVER_receive_done (client, GNUNET_OK);
998 struct GNUNET_NAMESTORE_Client *nc;
1003 handle_zone_to_name_it (void *cls,
1004 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1005 struct GNUNET_TIME_Absolute expire,
1007 unsigned int rd_count,
1008 const struct GNUNET_NAMESTORE_RecordData *rd,
1009 const struct GNUNET_CRYPTO_RsaSignature *signature)
1011 struct ZoneToNameCtx * ztn_ctx = cls;
1012 struct ZoneToNameResponseMessage *ztnr_msg;
1013 int16_t res = GNUNET_SYSERR;
1014 uint16_t name_len = 0;
1015 uint16_t rd_ser_len = 0 ;
1016 int32_t contains_sig = 0;
1017 size_t msg_size = 0;
1019 char *rd_ser = NULL;
1024 if ((zone_key != NULL) && (name != NULL))
1027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1029 name_len = strlen (name);
1033 /* no result found */
1034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1041 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1042 rd_ser = GNUNET_malloc (rd_ser_len);
1043 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1048 if (signature != NULL)
1049 contains_sig = GNUNET_YES;
1051 contains_sig = GNUNET_NO;
1055 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1056 ztnr_msg = GNUNET_malloc (msg_size);
1058 name_tmp = (char *) &ztnr_msg[1];
1059 rd_tmp = &name_tmp[name_len];
1060 sig_tmp = &rd_tmp[rd_ser_len];
1062 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1063 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1064 ztnr_msg->gns_header.header.size = htons (msg_size);
1065 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1066 ztnr_msg->res = htons (res);
1067 ztnr_msg->rd_len = htons (rd_ser_len);
1068 ztnr_msg->rd_count = htons (rd_count);
1069 ztnr_msg->name_len = htons (name_len);
1070 ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1071 if (zone_key != NULL)
1072 ztnr_msg->zone_key = *zone_key;
1074 memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1076 memcpy (name_tmp, name, name_len);
1078 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);
1079 memcpy (rd_tmp, rd_ser, rd_ser_len);
1080 memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1082 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1083 GNUNET_free (ztnr_msg);
1084 GNUNET_free_non_null (rd_ser);
1088 static void handle_zone_to_name (void *cls,
1089 struct GNUNET_SERVER_Client * client,
1090 const struct GNUNET_MessageHeader * message)
1092 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1093 struct GNUNET_NAMESTORE_Client *nc;
1094 struct ZoneToNameCtx ztn_ctx;
1095 size_t msg_size = 0;
1100 if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1102 GNUNET_break_op (0);
1103 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1107 nc = client_lookup(client);
1110 GNUNET_break_op (0);
1111 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1115 struct ZoneToNameMessage *ztn_msg = (struct ZoneToNameMessage *) message;
1117 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1119 GNUNET_break_op (0);
1120 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1124 rid = ntohl (ztn_msg->gns_header.r_id);
1129 char * z_tmp = strdup (GNUNET_h2s (&ztn_msg->zone));
1130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1132 GNUNET_h2s (&ztn_msg->value_zone));
1133 GNUNET_free (z_tmp);
1135 res = GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1137 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1140 struct ZoneIterationProcResult
1143 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1146 struct GNUNET_CRYPTO_RsaSignature signature;
1147 struct GNUNET_TIME_Absolute expire;
1157 void zone_iteration_proc (void *cls,
1158 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1159 struct GNUNET_TIME_Absolute expire,
1161 unsigned int rd_count,
1162 const struct GNUNET_NAMESTORE_RecordData *rd,
1163 const struct GNUNET_CRYPTO_RsaSignature *signature)
1165 struct ZoneIterationProcResult *zipr = cls;
1167 if (zone_key != NULL)
1169 zipr->zone_key = *zone_key;
1170 zipr->have_zone_key = GNUNET_YES;
1173 zipr->have_zone_key = GNUNET_NO;
1175 zipr->expire = expire;
1179 memcpy (zipr->name, name, strlen(name) + 1);
1180 zipr->have_name = GNUNET_YES;
1183 zipr->have_name = GNUNET_NO;
1185 if (signature != NULL)
1187 zipr->signature = *signature;
1188 zipr->have_signature = GNUNET_YES;
1191 zipr->have_signature = GNUNET_NO;
1193 if ((rd_count > 0) && (rd != NULL))
1195 len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1196 zipr->rd_ser = GNUNET_malloc (len);
1197 GNUNET_NAMESTORE_records_serialize(rd_count, rd, len, zipr->rd_ser);
1198 zipr->rd_ser_len = len;
1202 static void handle_iteration_start (void *cls,
1203 struct GNUNET_SERVER_Client * client,
1204 const struct GNUNET_MessageHeader * message)
1206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
1208 struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message;
1209 struct GNUNET_NAMESTORE_Client *nc;
1210 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1211 struct ZoneIterationResponseMessage zir_msg;
1212 struct ZoneIterationProcResult zipr;
1215 nc = client_lookup(client);
1218 GNUNET_break_op (0);
1219 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1223 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
1224 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1227 zi->zone = zis_msg->zone;
1229 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1231 res = GSN_database->iterate_records (GSN_database->cls, &zis_msg->zone, NULL, zi->offset , &zone_iteration_proc, &zipr);
1234 /* GNUNET_OK on success */
1238 /* GNUNET_SYSERR on error */
1241 /* GNUNET_NO if there were no results, */
1249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_RESPONSE");
1250 zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1251 zir_msg.gns_header.r_id = htonl(zi->request_id);
1252 zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1255 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1258 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1261 static void handle_iteration_stop (void *cls,
1262 struct GNUNET_SERVER_Client * client,
1263 const struct GNUNET_MessageHeader * message)
1265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1267 struct GNUNET_NAMESTORE_Client *nc;
1268 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1269 struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1272 nc = client_lookup(client);
1275 GNUNET_break_op (0);
1276 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1280 rid = ntohl (zis_msg->gns_header.r_id);
1281 for (zi = nc->op_head; zi != NULL; zi = zi->next)
1283 if (zi->request_id == rid)
1288 GNUNET_break_op (0);
1289 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1293 GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone));
1297 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1300 static void handle_iteration_next (void *cls,
1301 struct GNUNET_SERVER_Client * client,
1302 const struct GNUNET_MessageHeader * message)
1304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1306 struct GNUNET_NAMESTORE_Client *nc;
1307 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1308 struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1312 nc = client_lookup(client);
1315 GNUNET_break_op (0);
1316 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1320 rid = ntohl (zis_msg->gns_header.r_id);
1321 for (zi = nc->op_head; zi != NULL; zi = zi->next)
1323 if (zi->request_id == rid)
1328 GNUNET_break_op (0);
1329 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1334 res = GSN_database->iterate_records (GSN_database->cls, &zi->zone, NULL, zi->offset , &zone_iteration_proc, zi);
1340 * Process template requests.
1342 * @param cls closure
1343 * @param server the initialized server
1344 * @param cfg configuration to use
1347 run (void *cls, struct GNUNET_SERVER_Handle *server,
1348 const struct GNUNET_CONFIGURATION_Handle *cfg)
1352 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1354 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1355 {&handle_start, NULL,
1356 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
1357 {&handle_lookup_name, NULL,
1358 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
1359 {&handle_record_put, NULL,
1360 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
1361 {&handle_record_create, NULL,
1362 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
1363 {&handle_record_remove, NULL,
1364 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
1365 {&handle_zone_to_name, NULL,
1366 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
1367 {&handle_iteration_start, NULL,
1368 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
1369 {&handle_iteration_next, NULL,
1370 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
1371 {&handle_iteration_stop, NULL,
1372 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0},
1378 /* Loading database plugin */
1380 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
1382 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1384 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1385 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1386 if (GSN_database == NULL)
1387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
1389 GNUNET_free (database);
1391 /* Configuring server handles */
1392 GNUNET_SERVER_add_handlers (server, handlers);
1393 snc = GNUNET_SERVER_notification_context_create (server, 16);
1394 GNUNET_SERVER_disconnect_notify (server,
1395 &client_disconnect_notification,
1398 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1405 * The main function for the template service.
1407 * @param argc number of arguments from the command line
1408 * @param argv command line arguments
1409 * @return 0 ok, 1 on error
1412 main (int argc, char *const *argv)
1414 return (GNUNET_OK ==
1415 GNUNET_SERVICE_run (argc, argv, "namestore",
1416 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1419 /* end of gnunet-service-namestore.c */