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_util_lib.h"
28 #include "gnunet_dnsparser_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "gnunet_signatures.h"
32 #include "namestore.h"
34 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
37 * A namestore operation.
39 struct GNUNET_NAMESTORE_ZoneIteration
42 * Next element in the DLL
44 struct GNUNET_NAMESTORE_ZoneIteration *next;
47 * Previous element in the DLL
49 struct GNUNET_NAMESTORE_ZoneIteration *prev;
52 * Namestore client which intiated this zone iteration
54 struct GNUNET_NAMESTORE_Client *client;
57 * GNUNET_YES if we iterate over a specific zone
58 * GNUNET_NO if we iterate over all zones
63 * Hash of the specific zone if 'has_zone' is GNUNET_YES,
64 * othwerwise set to '\0'
66 struct GNUNET_CRYPTO_ShortHashCode zone;
69 * The operation id fot the zone iteration in the response for the client
74 * Offset of the zone iteration used to address next result of the zone
75 * iteration in the store
77 * Initialy set to 0 in handle_iteration_start
78 * Incremented with by every call to handle_iteration_next
83 * Which flags must be included
85 uint16_t must_have_flags;
88 * Which flags must not be included
90 uint16_t must_not_have_flags;
97 struct GNUNET_NAMESTORE_Client
100 * Next element in the DLL
102 struct GNUNET_NAMESTORE_Client *next;
105 * Previous element in the DLL
107 struct GNUNET_NAMESTORE_Client *prev;
112 struct GNUNET_SERVER_Client *client;
116 * Zone iteration operations in progress initiated by this client
118 struct GNUNET_NAMESTORE_ZoneIteration *op_head;
122 * Zone iteration operations in progress initiated by this client
124 struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
129 * A container struct to store information belonging to a zone crypto key pair
131 struct GNUNET_NAMESTORE_CryptoContainer
134 * Filename where to store the container
139 * Short hash of the zone's public key
141 struct GNUNET_CRYPTO_ShortHashCode zone;
146 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
152 * Configuration handle.
154 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
159 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
164 static char *zonefile_directory;
167 * Name of the database plugin
169 static char *db_lib_name;
172 * Our notification context.
174 static struct GNUNET_SERVER_NotificationContext *snc;
177 * Head of the Client DLL
179 static struct GNUNET_NAMESTORE_Client *client_head;
182 * Tail of the Client DLL
184 static struct GNUNET_NAMESTORE_Client *client_tail;
187 * Hashmap containing the zone keys this namestore has is authoritative for
189 * Keys are the GNUNET_CRYPTO_HashCode of the GNUNET_CRYPTO_ShortHashCode
190 * The values are 'struct GNUNET_NAMESTORE_CryptoContainer *'
192 static struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
195 * DLL head for key loading contexts
197 static struct KeyLoadContext *kl_head;
200 * DLL tail for key loading contexts
202 static struct KeyLoadContext *kl_tail;
204 struct KeyLoadContext
206 struct KeyLoadContext *next;
207 struct KeyLoadContext *prev;
208 struct GNUNET_CRYPTO_RsaKeyGenerationContext *keygen;
210 unsigned int *counter;
215 * Writes the encrypted private key of a zone in a file
217 * @param filename where to store the zone
218 * @param c the crypto container containing private key of the zone
219 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
222 write_key_to_file (const char *filename,
223 struct GNUNET_NAMESTORE_CryptoContainer *c)
225 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
226 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
227 struct GNUNET_DISK_FileHandle *fd;
228 struct GNUNET_CRYPTO_ShortHashCode zone;
229 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
230 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
232 fd = GNUNET_DISK_file_open (filename,
233 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS,
234 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
235 if ( (NULL == fd) && (EEXIST == errno) )
237 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
241 _("Failed to write zone key to file `%s': %s\n"),
243 _("file exists but reading key failed"));
244 return GNUNET_SYSERR;
246 GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
247 GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
248 GNUNET_CRYPTO_rsa_key_free (privkey);
249 if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
252 "File zone `%s' containing this key already exists\n",
253 GNUNET_short_h2s (&zone));
256 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
257 _("Failed to write zone key to file `%s': %s\n"),
259 _("file exists with different key"));
264 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
265 return GNUNET_SYSERR;
267 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
269 GNUNET_break (GNUNET_YES == GNUNET_DISK_file_close (fd));
270 return GNUNET_SYSERR;
272 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
273 GNUNET_assert (NULL != enc);
274 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
276 GNUNET_DISK_file_sync (fd);
277 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
278 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
279 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281 "Stored zonekey for zone `%s' in file `%s'\n",
282 GNUNET_short_h2s(&c->zone), c->filename);
288 * Write allthe given zone key to disk and then removes the entry from the
289 * 'zonekeys' hash map.
292 * @param key zone key
293 * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
295 * @return GNUNET_OK to continue iteration
298 zone_to_disk_it (void *cls,
299 const struct GNUNET_HashCode *key,
302 struct GNUNET_NAMESTORE_CryptoContainer *c = value;
304 if (NULL == c->filename)
305 GNUNET_asprintf(&c->filename,
308 GNUNET_short_h2s (&c->zone));
309 (void) write_key_to_file(c->filename, c);
310 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
311 GNUNET_CRYPTO_rsa_key_free (c->privkey);
312 GNUNET_free (c->filename);
319 * Add the given private key to the set of private keys
320 * this namestore can use to sign records when needed.
322 * @param pkey private key to add to our list (reference will
323 * be taken over or freed and should not be used afterwards)
326 learn_private_key (struct GNUNET_CRYPTO_RsaPrivateKey *pkey)
328 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
329 struct GNUNET_HashCode long_hash;
330 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
331 struct GNUNET_NAMESTORE_CryptoContainer *cc;
333 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
334 GNUNET_CRYPTO_short_hash (&pub,
335 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
337 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
339 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
341 GNUNET_CRYPTO_rsa_key_free (pkey);
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
345 "Received new private key for zone `%s'\n",
346 GNUNET_short_h2s(&pubkey_hash));
347 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
349 cc->zone = pubkey_hash;
350 GNUNET_assert (GNUNET_YES ==
351 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc,
352 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
357 * Returns the expiration time of the given block of records. The block
358 * expiration time is the expiration time of the block with smallest
361 * @param rd_count number of records given in 'rd'
362 * @param rd array of records
363 * @return absolute expiration time
365 static struct GNUNET_TIME_Absolute
366 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
369 struct GNUNET_TIME_Absolute expire;
370 struct GNUNET_TIME_Absolute at;
371 struct GNUNET_TIME_Relative rt;
374 return GNUNET_TIME_UNIT_ZERO_ABS;
375 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
376 for (c = 0; c < rd_count; c++)
378 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
380 rt.rel_value = rd[c].expiration_time;
381 at = GNUNET_TIME_relative_to_absolute (rt);
385 at.abs_value = rd[c].expiration_time;
387 expire = GNUNET_TIME_absolute_min (at, expire);
394 * Task run during shutdown.
400 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
402 struct GNUNET_NAMESTORE_ZoneIteration *no;
403 struct GNUNET_NAMESTORE_Client *nc;
404 struct KeyLoadContext *kl;
406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
409 GNUNET_SERVER_notification_context_destroy (snc);
413 while (NULL != (kl = kl_head))
415 GNUNET_CONTAINER_DLL_remove (kl_head, kl_tail, kl);
416 if (NULL != kl->keygen)
417 GNUNET_CRYPTO_rsa_key_create_stop (kl->keygen);
418 GNUNET_free (kl->filename);
422 GNUNET_CONTAINER_multihashmap_iterate (zonekeys, &zone_to_disk_it, NULL);
423 GNUNET_CONTAINER_multihashmap_destroy (zonekeys);
425 while (NULL != (nc = client_head))
427 while (NULL != (no = nc->op_head))
429 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
432 GNUNET_SERVER_client_drop(nc->client);
433 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
436 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
437 GNUNET_free (db_lib_name);
439 GNUNET_free_non_null (zonefile_directory);
440 zonefile_directory = NULL;
445 * Lookup our internal data structure for a given client.
447 * @param client server client handle to use for the lookup
448 * @return our internal structure for the client, NULL if
449 * we do not have any yet
451 static struct GNUNET_NAMESTORE_Client *
452 client_lookup (struct GNUNET_SERVER_Client *client)
454 struct GNUNET_NAMESTORE_Client *nc;
456 GNUNET_assert (NULL != client);
457 for (nc = client_head; NULL != nc; nc = nc->next)
458 if (client == nc->client)
465 * Called whenever a client is disconnected.
466 * Frees our resources associated with that client.
469 * @param client identification of the client
472 client_disconnect_notification (void *cls,
473 struct GNUNET_SERVER_Client *client)
475 struct GNUNET_NAMESTORE_ZoneIteration *no;
476 struct GNUNET_NAMESTORE_Client *nc;
480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
481 "Client %p disconnected\n",
483 if (NULL == (nc = client_lookup (client)))
485 while (NULL != (no = nc->op_head))
487 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
490 GNUNET_SERVER_client_drop (nc->client);
491 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
497 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
500 * @param client GNUNET_SERVER_Client sending the message
501 * @param message unused
504 handle_start (void *cls,
505 struct GNUNET_SERVER_Client *client,
506 const struct GNUNET_MessageHeader *message)
508 struct GNUNET_NAMESTORE_Client *nc;
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511 "Client %p connected\n", client);
512 if (NULL != client_lookup (client))
515 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
518 nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
520 GNUNET_SERVER_notification_context_add (snc, client);
521 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc);
522 GNUNET_SERVER_client_keep (client);
523 GNUNET_SERVER_receive_done (client, GNUNET_OK);
528 * Context for name lookups passed from 'handle_lookup_name' to
529 * 'handle_lookup_name_it' as closure
531 struct LookupNameContext
534 * The client to send the response to
536 struct GNUNET_NAMESTORE_Client *nc;
541 const struct GNUNET_CRYPTO_ShortHashCode *zone;
549 * Operation id for the name lookup
554 * Requested specific record type
556 uint32_t record_type;
561 * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
563 * @param cls a 'struct LookupNameContext *' with information about the request
564 * @param zone_key zone key of the zone
565 * @param expire expiration time
567 * @param rd_count number of records
568 * @param rd array of records
569 * @param signature signature
572 handle_lookup_name_it (void *cls,
573 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
574 struct GNUNET_TIME_Absolute expire,
576 unsigned int rd_count,
577 const struct GNUNET_NAMESTORE_RecordData *rd,
578 const struct GNUNET_CRYPTO_RsaSignature *signature)
580 struct LookupNameContext *lnc = cls;
581 struct LookupNameResponseMessage *lnr_msg;
582 struct GNUNET_NAMESTORE_RecordData *rd_selected;
583 struct GNUNET_NAMESTORE_CryptoContainer *cc;
584 struct GNUNET_CRYPTO_RsaSignature *signature_new;
585 struct GNUNET_TIME_Absolute e;
586 struct GNUNET_TIME_Relative re;
587 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
588 struct GNUNET_HashCode long_hash;
595 int contains_signature;
600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
601 "Found %u records under name `%s'\n",
604 authoritative = GNUNET_NO;
605 signature_new = NULL;
607 if (NULL != zone_key)
609 GNUNET_CRYPTO_short_hash (zone_key,
610 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
612 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
613 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get (zonekeys, &long_hash)))
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "Am authoritative for zone `%s'\n",
617 GNUNET_short_h2s (&zone_key_hash));
618 authoritative = GNUNET_YES;
623 rd_modified = GNUNET_NO;
625 /* count records to copy */
626 for (c = 0; c < rd_count; c++)
628 if ( (GNUNET_YES == authoritative) &&
630 GNUNET_NAMESTORE_is_expired (&rd[c]) ) )
632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
633 "Skipping expired record\n");
636 if ( (GNUNET_NAMESTORE_TYPE_ANY == lnc->record_type) ||
637 (rd[c].record_type == lnc->record_type) )
638 copied_elements++; /* found matching record */
641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
642 "Skipping non-mtaching record\n");
643 rd_modified = GNUNET_YES;
646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
647 "Found %u records with type %u for name `%s' in zone `%s'\n",
651 GNUNET_short_h2s(lnc->zone));
652 if (copied_elements > 0)
654 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
656 for (c = 0; c < rd_count; c++)
658 if ( (GNUNET_YES == authoritative) &&
660 GNUNET_NAMESTORE_is_expired (&rd[c])) )
662 if ( (GNUNET_NAMESTORE_TYPE_ANY == lnc->record_type) ||
663 (rd[c].record_type == lnc->record_type) )
665 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
667 GNUNET_break (GNUNET_YES == authoritative);
668 rd_modified = GNUNET_YES;
669 re.rel_value = rd[c].expiration_time;
670 e = GNUNET_TIME_relative_to_absolute (re);
674 e.abs_value = rd[c].expiration_time;
676 /* found matching record, copy and convert flags to public format */
677 rd_selected[copied_elements] = rd[c]; /* shallow copy! */
678 rd_selected[copied_elements].expiration_time = e.abs_value;
679 if (0 != (rd_selected[copied_elements].flags &
680 (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION | GNUNET_NAMESTORE_RF_AUTHORITY)))
682 rd_selected[copied_elements].flags &= ~ (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION |
683 GNUNET_NAMESTORE_RF_AUTHORITY);
684 rd_modified = GNUNET_YES;
690 rd_modified = GNUNET_YES;
697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
698 "Found %u matching records for name `%s' in zone `%s'\n",
701 GNUNET_short_h2s (lnc->zone));
702 contains_signature = GNUNET_NO;
703 if (copied_elements > 0)
705 if (GNUNET_YES == authoritative)
707 GNUNET_assert (NULL != cc);
708 e = get_block_expiration_time (rd_count, rd);
709 signature_new = GNUNET_NAMESTORE_create_signature (cc->privkey, e, name, rd_selected, copied_elements);
710 GNUNET_assert (NULL != signature_new);
711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
712 "Creating signature for name `%s' with %u records in zone `%s'\n",
715 GNUNET_short_h2s(&zone_key_hash));
719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
720 "Not authoritative, records modified is %d, have sig is %d\n",
723 if ((GNUNET_NO == rd_modified) && (NULL != signature))
724 contains_signature = GNUNET_YES; /* returning all records, so include signature */
728 rd_ser_len = GNUNET_NAMESTORE_records_get_size (copied_elements, rd_selected);
729 name_len = (NULL == name) ? 0 : strlen(name) + 1;
730 r_size = sizeof (struct LookupNameResponseMessage) +
731 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735 "Sending `%s' message\n",
736 "NAMESTORE_LOOKUP_NAME_RESPONSE");
737 lnr_msg = GNUNET_malloc (r_size);
738 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
739 lnr_msg->gns_header.header.size = ntohs (r_size);
740 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
741 lnr_msg->rd_count = htons (copied_elements);
742 lnr_msg->rd_len = htons (rd_ser_len);
743 lnr_msg->name_len = htons (name_len);
744 lnr_msg->expire = GNUNET_TIME_absolute_hton (get_block_expiration_time (copied_elements,
746 name_tmp = (char *) &lnr_msg[1];
747 memcpy (name_tmp, name, name_len);
748 rd_tmp = &name_tmp[name_len];
749 GNUNET_NAMESTORE_records_serialize (copied_elements, rd_selected, rd_ser_len, rd_tmp);
750 if (rd_selected != rd)
751 GNUNET_free_non_null (rd_selected);
752 if (NULL != zone_key)
753 lnr_msg->public_key = *zone_key;
754 if ( (GNUNET_YES == authoritative) &&
755 (copied_elements > 0) )
757 /* use new created signature */
758 lnr_msg->contains_sig = htons (GNUNET_YES);
759 GNUNET_assert (NULL != signature_new);
760 lnr_msg->signature = *signature_new;
761 GNUNET_free (signature_new);
763 else if (GNUNET_YES == contains_signature)
765 /* use existing signature */
766 lnr_msg->contains_sig = htons (GNUNET_YES);
767 GNUNET_assert (NULL != signature);
768 lnr_msg->signature = *signature;
770 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client,
771 &lnr_msg->gns_header.header,
773 GNUNET_free (lnr_msg);
778 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
781 * @param client GNUNET_SERVER_Client sending the message
782 * @param message message of type 'struct LookupNameMessage'
785 handle_lookup_name (void *cls,
786 struct GNUNET_SERVER_Client *client,
787 const struct GNUNET_MessageHeader *message)
789 const struct LookupNameMessage *ln_msg;
790 struct LookupNameContext lnc;
791 struct GNUNET_NAMESTORE_Client *nc;
798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
799 "Received `%s' message\n",
800 "NAMESTORE_LOOKUP_NAME");
801 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
804 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
807 if (NULL == (nc = client_lookup(client)))
810 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
813 ln_msg = (const struct LookupNameMessage *) message;
814 rid = ntohl (ln_msg->gns_header.r_id);
815 name_len = ntohl (ln_msg->name_len);
816 type = ntohl (ln_msg->record_type);
817 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
820 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
823 name = (const char *) &ln_msg[1];
824 if ('\0' != name[name_len -1])
827 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
830 if (GNUNET_NAMESTORE_TYPE_ANY == type)
831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
832 "Looking up all records for name `%s' in zone `%s'\n",
834 GNUNET_short_h2s(&ln_msg->zone));
836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
837 "Looking up records with type %u for name `%s' in zone `%s'\n",
839 GNUNET_short_h2s(&ln_msg->zone));
841 conv_name = GNUNET_NAMESTORE_normalize_string (name);
842 if (NULL == conv_name)
844 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
845 "Error converting name `%s'\n", name);
849 /* do the actual lookup */
850 lnc.request_id = rid;
852 lnc.record_type = type;
853 lnc.name = conv_name;
854 lnc.zone = &ln_msg->zone;
856 GSN_database->iterate_records (GSN_database->cls,
857 &ln_msg->zone, conv_name, 0 /* offset */,
858 &handle_lookup_name_it, &lnc))
860 /* internal error (in database plugin); might be best to just hang up on
861 plugin rather than to signal that there are 'no' results, which
862 might also be false... */
864 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
865 GNUNET_free (conv_name);
868 GNUNET_free (conv_name);
869 GNUNET_SERVER_receive_done (client, GNUNET_OK);
874 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
877 * @param client GNUNET_SERVER_Client sending the message
878 * @param message message of type 'struct RecordPutMessage'
881 handle_record_put (void *cls,
882 struct GNUNET_SERVER_Client *client,
883 const struct GNUNET_MessageHeader *message)
885 struct GNUNET_NAMESTORE_Client *nc;
886 const struct RecordPutMessage *rp_msg;
887 struct GNUNET_TIME_Absolute expire;
888 const struct GNUNET_CRYPTO_RsaSignature *signature;
889 struct RecordPutResponseMessage rpr_msg;
890 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
902 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
903 "Received `%s' message\n",
904 "NAMESTORE_RECORD_PUT");
905 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
908 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
911 if (NULL == (nc = client_lookup (client)))
914 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
917 rp_msg = (const struct RecordPutMessage *) message;
918 rid = ntohl (rp_msg->gns_header.r_id);
919 msg_size = ntohs (rp_msg->gns_header.header.size);
920 name_len = ntohs (rp_msg->name_len);
921 rd_count = ntohs (rp_msg->rd_count);
922 rd_ser_len = ntohs (rp_msg->rd_len);
923 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >= MAX_NAME_LEN) || (0 == name_len))
926 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
929 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
930 if (msg_size != msg_size_exp)
933 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
936 name = (const char *) &rp_msg[1];
937 if ('\0' != name[name_len -1])
940 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
943 expire = GNUNET_TIME_absolute_ntoh (rp_msg->expire);
944 signature = &rp_msg->signature;
945 rd_ser = &name[name_len];
946 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
949 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
952 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
955 GNUNET_CRYPTO_short_hash (&rp_msg->public_key,
956 sizeof (rp_msg->public_key),
959 conv_name = GNUNET_NAMESTORE_normalize_string (name);
960 if (NULL == conv_name)
962 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
963 "Error converting name `%s'\n", name);
967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
968 "Putting %u records under name `%s' in zone `%s'\n",
970 GNUNET_short_h2s (&zone_hash));
971 res = GSN_database->put_records(GSN_database->cls,
977 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
978 "Putting record for name `%s': %s\n",
980 (GNUNET_OK == res) ? "OK" : "FAILED");
981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
982 "Sending `%s' message\n",
983 "RECORD_PUT_RESPONSE");
984 GNUNET_free (conv_name);
985 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
986 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
987 rpr_msg.gns_header.r_id = htonl (rid);
988 rpr_msg.op_result = htonl (res);
989 GNUNET_SERVER_notification_context_unicast (snc,
991 &rpr_msg.gns_header.header,
993 GNUNET_SERVER_receive_done (client, GNUNET_OK);
998 * Context for record create operations passed from 'handle_record_create' to
999 * 'handle_create_record_it' as closure
1001 struct CreateRecordContext
1006 const struct GNUNET_NAMESTORE_RecordData *rd;
1011 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
1014 * Name for the record to create
1019 * Record expiration time
1021 struct GNUNET_TIME_Absolute expire;
1024 * result returned from 'handle_create_record_it'
1025 * GNUNET_SYSERR: failed to create the record
1026 * GNUNET_NO: we updated an existing record or identical entry existed
1027 * GNUNET_YES : we created a new record
1034 * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
1035 * in handle_record_create
1037 * @param cls a 'struct CreateRecordContext *' with information about the request
1038 * @param pubkey zone key of the zone
1039 * @param expire expiration time
1041 * @param rd_count number of records
1042 * @param rd array of records
1043 * @param signature signature
1046 handle_create_record_it (void *cls,
1047 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
1048 struct GNUNET_TIME_Absolute expire,
1050 unsigned int rd_count,
1051 const struct GNUNET_NAMESTORE_RecordData *rd,
1052 const struct GNUNET_CRYPTO_RsaSignature *signature)
1054 static struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1055 struct CreateRecordContext *crc = cls;
1056 struct GNUNET_NAMESTORE_RecordData *rd_new;
1057 struct GNUNET_TIME_Absolute block_expiration;
1061 unsigned int rd_count_new;
1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1064 "Found %u existing records for `%s'\n",
1065 rd_count, crc->name);
1068 for (c = 0; c < rd_count; c++)
1070 if ( (crc->rd->record_type != rd[c].record_type) ||
1071 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
1072 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1073 continue; /* no match */
1074 if ( (GNUNET_NAMESTORE_TYPE_PKEY == crc->rd->record_type) ||
1075 (GNUNET_NAMESTORE_TYPE_PSEU == crc->rd->record_type) ||
1076 (GNUNET_DNSPARSER_TYPE_CNAME == crc->rd->record_type) )
1078 /* Update unique PKEY, PSEU or CNAME record; for these
1079 record types, only one can be active at any time */
1081 if ( (crc->rd->data_size != rd[c].data_size) ||
1082 (0 != memcmp (crc->rd->data, rd[c].data, rd[c].data_size)) ||
1083 (crc->rd->expiration_time != rd[c].expiration_time) )
1084 update = GNUNET_YES;
1087 if ( (crc->rd->data_size == rd[c].data_size) &&
1088 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
1090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1091 "Found matching existing record for `%s'; only updating expiration date!\n",
1094 if (crc->rd->expiration_time != rd[c].expiration_time)
1095 update = GNUNET_YES;
1100 if ( (-1 != exist) &&
1101 (GNUNET_NO == update) )
1103 /* Exact same record already exists */
1104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105 "Matching record for %s' exists, no change required!\n",
1107 crc->res = GNUNET_NO; /* identical record existed */
1112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1113 "No existing record for name `%s'!\n",
1115 rd_count_new = rd_count + 1;
1116 rd_new = GNUNET_malloc (rd_count_new * sizeof (struct GNUNET_NAMESTORE_RecordData));
1117 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1118 rd_new[rd_count] = *(crc->rd);
1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1123 "Updating existing records for `%s'!\n",
1125 rd_count_new = rd_count;
1126 rd_new = GNUNET_malloc (rd_count_new * sizeof (struct GNUNET_NAMESTORE_RecordData));
1127 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1128 rd_new[exist] = *(crc->rd);
1130 block_expiration = GNUNET_TIME_absolute_max (crc->expire, expire);
1132 GSN_database->put_records (GSN_database->cls,
1136 rd_count_new, rd_new,
1138 crc->res = GNUNET_SYSERR; /* error */
1139 else if (GNUNET_YES == update)
1140 crc->res = GNUNET_NO; /* update */
1142 crc->res = GNUNET_YES; /* created new record */
1143 GNUNET_free (rd_new);
1148 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1151 * @param client GNUNET_SERVER_Client sending the message
1152 * @param message message of type 'struct RecordCreateMessage'
1155 handle_record_create (void *cls,
1156 struct GNUNET_SERVER_Client *client,
1157 const struct GNUNET_MessageHeader *message)
1159 struct GNUNET_NAMESTORE_Client *nc;
1160 const struct RecordCreateMessage *rp_msg;
1161 struct CreateRecordContext crc;
1162 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1163 struct RecordCreateResponseMessage rcr_msg;
1166 size_t msg_size_exp;
1170 const char *pkey_tmp;
1171 const char *name_tmp;
1174 unsigned int rd_count;
1176 struct GNUNET_NAMESTORE_RecordData rd;
1177 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1180 "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1181 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1184 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1187 if (NULL == (nc = client_lookup (client)))
1190 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1193 rp_msg = (const struct RecordCreateMessage *) message;
1194 rid = ntohl (rp_msg->gns_header.r_id);
1195 name_len = ntohs (rp_msg->name_len);
1196 msg_size = ntohs (message->size);
1197 rd_count = ntohs (rp_msg->rd_count);
1198 rd_ser_len = ntohs (rp_msg->rd_len);
1199 key_len = ntohs (rp_msg->pkey_len);
1200 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1201 if ( (msg_size != msg_size_exp) || (1 != rd_count) )
1204 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1207 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1210 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1213 pkey_tmp = (const char *) &rp_msg[1];
1214 name_tmp = &pkey_tmp[key_len];
1215 rd_ser = &name_tmp[name_len];
1216 if ('\0' != name_tmp[name_len -1])
1219 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1222 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1225 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1229 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, &rd))
1232 GNUNET_CRYPTO_rsa_key_free (pkey);
1233 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1237 /* Extracting and converting private key */
1238 GNUNET_CRYPTO_rsa_key_get_public (pkey, &crc.pubkey);
1239 GNUNET_CRYPTO_short_hash (&crc.pubkey,
1240 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1242 learn_private_key (pkey);
1244 conv_name = GNUNET_NAMESTORE_normalize_string(name_tmp);
1245 if (NULL == conv_name)
1247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1248 "Error converting name `%s'\n", name_tmp);
1251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1252 "Creating record for name `%s' in zone `%s'\n",
1253 conv_name, GNUNET_short_h2s(&pubkey_hash));
1254 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1255 crc.res = GNUNET_SYSERR;
1257 crc.name = conv_name;
1259 /* Get existing records for name */
1260 res = GSN_database->iterate_records (GSN_database->cls, &pubkey_hash, conv_name, 0,
1261 &handle_create_record_it, &crc);
1262 GNUNET_free (conv_name);
1263 if (res != GNUNET_SYSERR)
1267 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1268 "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1269 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1270 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1271 rcr_msg.gns_header.r_id = htonl (rid);
1272 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1273 rcr_msg.op_result = htonl (GNUNET_YES);
1274 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1275 rcr_msg.op_result = htonl (GNUNET_NO);
1277 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1278 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
1279 &rcr_msg.gns_header.header,
1281 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1286 * Context for record remove operations passed from 'handle_record_remove' to
1287 * 'handle_record_remove_it' as closure
1289 struct RemoveRecordContext
1294 const struct GNUNET_NAMESTORE_RecordData *rd;
1297 * See RECORD_REMOVE_RESULT_*-codes. Set by 'handle_record_remove_it'
1298 * to the result of the operation.
1305 * We are to remove a record (or all records for a given name). This function
1306 * will be called with the existing records (if there are any) and is to then
1307 * compute what to keep and trigger the necessary changes.
1309 * @param cls the 'struct RecordRemoveContext' with information about what to remove
1310 * @param zone_key public key of the zone
1311 * @param expire when does the corresponding block in the DHT expire (until
1312 * when should we never do a DHT lookup for the same name again)?
1313 * @param name name that is being mapped (at most 255 characters long)
1314 * @param rd_count number of entries in 'rd' array
1315 * @param rd array of records with data to store
1316 * @param signature signature of the record block, NULL if signature is unavailable (i.e.
1317 * because the user queried for a particular record type only)
1320 handle_record_remove_it (void *cls,
1321 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1322 struct GNUNET_TIME_Absolute expire,
1324 unsigned int rd_count,
1325 const struct GNUNET_NAMESTORE_RecordData *rd,
1326 const struct GNUNET_CRYPTO_RsaSignature *signature)
1328 static struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1329 struct RemoveRecordContext *rrc = cls;
1332 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1335 "Name `%s 'currently has %u records\n",
1339 /* Could not find record to remove */
1340 rrc->op_res = RECORD_REMOVE_RESULT_NO_RECORDS;
1343 /* Find record to remove */
1345 for (c = 0; c < rd_count; c++)
1348 GNUNET_NAMESTORE_records_cmp (&rd[c],
1351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1357 /* Could not find record to remove */
1358 rrc->op_res = RECORD_REMOVE_RESULT_RECORD_NOT_FOUND;
1363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1364 "No records left for name `%s', removing name\n",
1366 GNUNET_CRYPTO_short_hash (zone_key,
1367 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1370 GSN_database->remove_records (GSN_database->cls,
1374 /* Could not remove records from database */
1375 rrc->op_res = RECORD_REMOVE_RESULT_FAILED_TO_REMOVE;
1378 rrc->op_res = RECORD_REMOVE_RESULT_SUCCESS;
1383 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count - 1];
1384 unsigned int c2 = 0;
1386 for (c = 0; c < rd_count; c++)
1390 rd_new[c2++] = rd[c];
1393 GSN_database->put_records(GSN_database->cls,
1397 rd_count - 1, rd_new,
1400 /* Could not put records into database */
1401 rrc->op_res = RECORD_REMOVE_RESULT_FAILED_TO_PUT_UPDATE;
1405 rrc->op_res = RECORD_REMOVE_RESULT_SUCCESS;
1410 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1413 * @param client GNUNET_SERVER_Client sending the message
1414 * @param message message of type 'struct RecordRemoveMessage'
1417 handle_record_remove (void *cls,
1418 struct GNUNET_SERVER_Client *client,
1419 const struct GNUNET_MessageHeader *message)
1421 struct GNUNET_NAMESTORE_Client *nc;
1422 const struct RecordRemoveMessage *rr_msg;
1423 struct RecordRemoveResponseMessage rrr_msg;
1424 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1425 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1426 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1427 struct GNUNET_NAMESTORE_RecordData rd;
1428 const char *pkey_tmp;
1429 const char *name_tmp;
1436 size_t msg_size_exp;
1439 struct RemoveRecordContext rrc;
1443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1444 "Received `%s' message\n",
1445 "NAMESTORE_RECORD_REMOVE");
1446 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1449 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1452 if (NULL == (nc = client_lookup(client)))
1455 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1458 rr_msg = (const struct RecordRemoveMessage *) message;
1459 rid = ntohl (rr_msg->gns_header.r_id);
1460 name_len = ntohs (rr_msg->name_len);
1461 rd_ser_len = ntohs (rr_msg->rd_len);
1462 rd_count = ntohs (rr_msg->rd_count);
1463 key_len = ntohs (rr_msg->pkey_len);
1464 msg_size = ntohs (message->size);
1465 if ((name_len >= MAX_NAME_LEN) || (0 == name_len) || (1 < rd_count) )
1468 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1471 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1472 if (msg_size != msg_size_exp)
1475 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1478 pkey_tmp = (const char *) &rr_msg[1];
1479 name_tmp = &pkey_tmp[key_len];
1480 rd_ser = &name_tmp[name_len];
1481 if ('\0' != name_tmp[name_len -1])
1484 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1487 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1490 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1493 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
1494 GNUNET_CRYPTO_short_hash (&pub,
1495 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1497 learn_private_key (pkey);
1499 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, &rd))
1502 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1506 conv_name = GNUNET_NAMESTORE_normalize_string(name_tmp);
1507 if (NULL == conv_name)
1509 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1510 "Error converting name `%s'\n", name_tmp);
1516 /* remove the whole name and all records */
1517 res = GSN_database->remove_records (GSN_database->cls,
1520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1521 "Removing name `%s': %s\n",
1522 conv_name, (GNUNET_OK == res) ? "OK" : "FAILED");
1523 if (GNUNET_OK != res)
1524 /* Could not remove entry from database */
1525 res = RECORD_REMOVE_RESULT_FAILED_TO_PUT_UPDATE;
1527 res = RECORD_REMOVE_RESULT_SUCCESS;
1531 /* remove a single record */
1532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1533 "Removing record for name `%s' in zone `%s'\n", conv_name,
1534 GNUNET_short_h2s (&pubkey_hash));
1536 rrc.op_res = RECORD_REMOVE_RESULT_RECORD_NOT_FOUND;
1539 while ( (RECORD_REMOVE_RESULT_RECORD_NOT_FOUND == rrc.op_res) &&
1540 (GNUNET_OK == res) )
1542 res = GSN_database->iterate_records (GSN_database->cls,
1546 &handle_record_remove_it, &rrc);
1554 GNUNET_break (RECORD_REMOVE_RESULT_NO_RECORDS == rrc.op_res);
1555 res = RECORD_REMOVE_RESULT_NO_RECORDS;
1556 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1557 _("Failed to find record to remove\n"));
1560 res = RECORD_REMOVE_RESULT_FAILED_ACCESS_DATABASE;
1564 res = RECORD_REMOVE_RESULT_FAILED_INTERNAL_ERROR;
1568 GNUNET_free (conv_name);
1569 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1570 "Sending `%s' message\n",
1571 "RECORD_REMOVE_RESPONSE");
1572 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1573 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1574 rrr_msg.gns_header.r_id = htonl (rid);
1575 rrr_msg.op_result = htonl (res);
1576 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
1577 &rrr_msg.gns_header.header,
1579 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1584 * Context for record remove operations passed from 'handle_zone_to_name' to
1585 * 'handle_zone_to_name_it' as closure
1587 struct ZoneToNameCtx
1592 struct GNUNET_NAMESTORE_Client *nc;
1595 * Request id (to be used in the response to the client).
1600 * Set to GNUNET_OK on success, GNUNET_SYSERR on error. Note that
1601 * not finding a name for the zone still counts as a 'success' here,
1602 * as this field is about the success of executing the IPC protocol.
1609 * Zone to name iterator
1611 * @param cls struct ZoneToNameCtx *
1612 * @param zone_key the zone key
1613 * @param expire expiration date
1615 * @param rd_count number of records
1616 * @param rd record data
1617 * @param signature signature
1620 handle_zone_to_name_it (void *cls,
1621 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1622 struct GNUNET_TIME_Absolute expire,
1624 unsigned int rd_count,
1625 const struct GNUNET_NAMESTORE_RecordData *rd,
1626 const struct GNUNET_CRYPTO_RsaSignature *signature)
1628 struct ZoneToNameCtx *ztn_ctx = cls;
1629 struct ZoneToNameResponseMessage *ztnr_msg;
1638 if ((NULL != zone_key) && (NULL != name))
1641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1642 "Found result: name `%s' has %u records\n",
1645 name_len = strlen (name) + 1;
1649 /* no result found */
1650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1651 "Found no results\n");
1655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1656 "Sending `%s' message\n",
1657 "ZONE_TO_NAME_RESPONSE");
1658 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1659 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1660 if (NULL != signature)
1661 msg_size += sizeof (struct GNUNET_CRYPTO_RsaSignature);
1662 if (msg_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1665 ztn_ctx->success = GNUNET_SYSERR;
1668 ztnr_msg = GNUNET_malloc (msg_size);
1669 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1670 ztnr_msg->gns_header.header.size = htons (msg_size);
1671 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1672 ztnr_msg->res = htons (res);
1673 ztnr_msg->rd_len = htons (rd_ser_len);
1674 ztnr_msg->rd_count = htons (rd_count);
1675 ztnr_msg->name_len = htons (name_len);
1676 ztnr_msg->expire = GNUNET_TIME_absolute_hton (expire);
1677 if (NULL != zone_key)
1678 ztnr_msg->zone_key = *zone_key;
1679 name_tmp = (char *) &ztnr_msg[1];
1681 memcpy (name_tmp, name, name_len);
1682 rd_tmp = &name_tmp[name_len];
1683 GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_tmp);
1684 sig_tmp = &rd_tmp[rd_ser_len];
1685 if (NULL != signature)
1686 memcpy (sig_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature));
1687 ztn_ctx->success = GNUNET_OK;
1688 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client,
1689 &ztnr_msg->gns_header.header,
1691 GNUNET_free (ztnr_msg);
1696 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1699 * @param client GNUNET_SERVER_Client sending the message
1700 * @param message message of type 'struct ZoneToNameMessage'
1703 handle_zone_to_name (void *cls,
1704 struct GNUNET_SERVER_Client *client,
1705 const struct GNUNET_MessageHeader *message)
1707 struct GNUNET_NAMESTORE_Client *nc;
1708 const struct ZoneToNameMessage *ztn_msg;
1709 struct ZoneToNameCtx ztn_ctx;
1711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1712 "Received `%s' message\n",
1714 ztn_msg = (const struct ZoneToNameMessage *) message;
1715 if (NULL == (nc = client_lookup(client)))
1718 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1721 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1723 ztn_ctx.success = GNUNET_SYSERR;
1724 if (GNUNET_SYSERR ==
1725 GSN_database->zone_to_name (GSN_database->cls,
1727 &ztn_msg->value_zone,
1728 &handle_zone_to_name_it, &ztn_ctx))
1730 /* internal error, hang up instead of signalling something
1731 that might be wrong */
1733 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1736 GNUNET_SERVER_receive_done (client, ztn_ctx.success);
1741 * Zone iteration processor result
1743 enum ZoneIterationResult
1746 * Found records, but all records were filtered
1747 * Continue to iterate
1749 IT_ALL_RECORDS_FILTERED = -1,
1753 * Continue to iterate with next iteration_next call
1755 IT_SUCCESS_MORE_AVAILABLE = 0,
1758 * Iteration complete
1760 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 1
1765 * Context for record remove operations passed from
1766 * 'run_zone_iteration_round' to 'zone_iteraterate_proc' as closure
1768 struct ZoneIterationProcResult
1771 * The zone iteration handle
1773 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1776 * Iteration result: iteration done?
1777 * IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
1778 * we got one for now and have sent it to the client
1779 * IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
1780 * IT_ALL_RECORDS_FILTERED: if all results were filtered so far.
1782 int res_iteration_finished;
1788 * Process results for zone iteration from database
1790 * @param cls struct ZoneIterationProcResult *proc
1791 * @param zone_key the zone key
1792 * @param expire expiration time
1794 * @param rd_count number of records for this name
1795 * @param rd record data
1796 * @param signature block signature
1799 zone_iteraterate_proc (void *cls,
1800 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1801 struct GNUNET_TIME_Absolute expire,
1803 unsigned int rd_count,
1804 const struct GNUNET_NAMESTORE_RecordData *rd,
1805 const struct GNUNET_CRYPTO_RsaSignature *signature)
1807 struct ZoneIterationProcResult *proc = cls;
1808 struct GNUNET_NAMESTORE_RecordData rd_filtered[rd_count];
1809 struct GNUNET_CRYPTO_RsaSignature *new_signature = NULL;
1810 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1811 struct GNUNET_HashCode long_hash;
1812 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1813 struct ZoneIterationResponseMessage *zir_msg;
1814 struct GNUNET_TIME_Relative rt;
1815 unsigned int rd_count_filtered;
1823 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1824 if ((NULL == zone_key) && (NULL == name))
1826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1827 "Iteration done\n");
1828 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1831 if ((NULL == zone_key) || (NULL == name))
1833 /* what is this!? should never happen */
1837 rd_count_filtered = 0;
1838 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1839 "Received result for zone iteration: `%s'\n",
1841 for (c = 0; c < rd_count; c++)
1843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1844 "Record %u has flags: %x must have flags are %x, must not have flags are %x\n",
1846 proc->zi->must_have_flags,
1847 proc->zi->must_not_have_flags);
1848 /* Checking must have flags, except 'relative-expiration' which is a special flag */
1849 if ((rd[c].flags & proc->zi->must_have_flags & (~GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
1850 != (proc->zi->must_have_flags & (~ GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)))
1852 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %u lacks 'must-have' flags: Not included\n", c);
1855 /* Checking must-not-have flags */
1856 if (0 != (rd[c].flags & proc->zi->must_not_have_flags))
1858 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1859 "Record %u has 'must-not-have' flags: Not included\n", c);
1862 rd_filtered[rd_count_filtered] = rd[c];
1863 /* convert relative to absolute expiration time unless explicitly requested otherwise */
1864 if ( (0 == (proc->zi->must_have_flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) &&
1865 (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1867 /* should convert relative-to-absolute expiration time */
1868 rt.rel_value = rd[c].expiration_time;
1869 rd_filtered[c].expiration_time = GNUNET_TIME_relative_to_absolute (rt).abs_value;
1870 rd_filtered[c].flags &= ~ GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
1872 /* we NEVER keep the 'authority' flag */
1873 rd_filtered[c].flags &= ~ GNUNET_NAMESTORE_RF_AUTHORITY;
1874 rd_count_filtered++;
1876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1877 "Included %u of %u records\n",
1878 rd_count_filtered, rd_count);
1881 if ( (rd_count_filtered > 0) &&
1882 (0 == (proc->zi->must_have_flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1884 /* compute / obtain signature, but only if we (a) have records and (b) expiration times were
1885 converted to absolute expiration times */
1886 GNUNET_CRYPTO_short_hash (zone_key,
1887 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1889 GNUNET_CRYPTO_short_hash_double (&zone_hash, &long_hash);
1890 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash)))
1892 expire = get_block_expiration_time (rd_count_filtered, rd_filtered);
1893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1894 "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1895 name, GNUNET_short_h2s(&zone_hash),
1897 (unsigned long long) expire.abs_value);
1898 new_signature = GNUNET_NAMESTORE_create_signature (cc->privkey, expire, name,
1899 rd_filtered, rd_count_filtered);
1900 GNUNET_assert (NULL != new_signature);
1901 signature = new_signature;
1903 else if (rd_count_filtered == rd_count)
1905 if (NULL != signature)
1907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1908 "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1909 name, GNUNET_short_h2s (&zone_hash), rd_count_filtered,
1910 (unsigned long long) expire.abs_value);
1915 if (rd_count_filtered == 0)
1917 /* After filtering records there are no records left to return */
1918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No records to transmit\n");
1919 proc->res_iteration_finished = IT_ALL_RECORDS_FILTERED;
1923 if (GNUNET_YES == proc->zi->has_zone)
1924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1925 "Sending name `%s' for iteration over zone `%s'\n",
1926 name, GNUNET_short_h2s(&proc->zi->zone));
1928 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1929 "Sending name `%s' for iteration over all zones\n",
1931 name_len = strlen (name) + 1;
1932 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count_filtered, rd_filtered);
1933 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1935 zir_msg = GNUNET_malloc (msg_size);
1936 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1937 zir_msg->gns_header.header.size = htons (msg_size);
1938 zir_msg->gns_header.r_id = htonl (proc->zi->request_id);
1939 zir_msg->expire = GNUNET_TIME_absolute_hton (expire);
1940 zir_msg->reserved = htons (0);
1941 zir_msg->name_len = htons (name_len);
1942 zir_msg->rd_count = htons (rd_count_filtered);
1943 zir_msg->rd_len = htons (rd_ser_len);
1944 if (NULL != signature)
1945 zir_msg->signature = *signature;
1946 zir_msg->public_key = *zone_key;
1947 name_tmp = (char *) &zir_msg[1];
1948 memcpy (name_tmp, name, name_len);
1949 rd_ser = &name_tmp[name_len];
1950 GNUNET_NAMESTORE_records_serialize (rd_count_filtered, rd_filtered, rd_ser_len, rd_ser);
1951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1952 "Sending `%s' message with size %u\n",
1953 "ZONE_ITERATION_RESPONSE",
1955 GNUNET_SERVER_notification_context_unicast (snc, proc->zi->client->client,
1956 (const struct GNUNET_MessageHeader *) zir_msg,
1958 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1959 GNUNET_free (zir_msg);
1960 GNUNET_free_non_null (new_signature);
1965 * Perform the next round of the zone iteration.
1967 * @param zi zone iterator to process
1970 run_zone_iteration_round (struct GNUNET_NAMESTORE_ZoneIteration *zi)
1972 struct ZoneIterationProcResult proc;
1973 struct ZoneIterationResponseMessage zir_end;
1974 struct GNUNET_CRYPTO_ShortHashCode *zone;
1976 memset (&proc, 0, sizeof (proc));
1978 if (GNUNET_YES == zi->has_zone)
1982 proc.res_iteration_finished = IT_ALL_RECORDS_FILTERED;
1983 while (IT_ALL_RECORDS_FILTERED == proc.res_iteration_finished)
1985 if (GNUNET_SYSERR ==
1986 GSN_database->iterate_records (GSN_database->cls, zone, NULL,
1988 &zone_iteraterate_proc, &proc))
1995 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1997 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1998 "More results available\n");
1999 return; /* more results later */
2001 if (GNUNET_YES == zi->has_zone)
2002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2003 "No more results for zone `%s'\n",
2004 GNUNET_short_h2s(&zi->zone));
2006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2007 "No more results for all zones\n");
2008 memset (&zir_end, 0, sizeof (zir_end));
2009 zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
2010 zir_end.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
2011 zir_end.gns_header.r_id = htonl(zi->request_id);
2012 GNUNET_SERVER_notification_context_unicast (snc,
2014 &zir_end.gns_header.header, GNUNET_NO);
2015 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2016 "Removing zone iterator\n");
2017 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
2023 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
2026 * @param client GNUNET_SERVER_Client sending the message
2027 * @param message message of type 'struct ZoneIterationStartMessage'
2030 handle_iteration_start (void *cls,
2031 struct GNUNET_SERVER_Client *client,
2032 const struct GNUNET_MessageHeader *message)
2034 static struct GNUNET_CRYPTO_ShortHashCode zeros;
2035 const struct ZoneIterationStartMessage *zis_msg;
2036 struct GNUNET_NAMESTORE_Client *nc;
2037 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2039 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2040 if (NULL == (nc = client_lookup (client)))
2043 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2046 zis_msg = (const struct ZoneIterationStartMessage *) message;
2047 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2048 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2051 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2052 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2053 if (0 == memcmp (&zeros, &zis_msg->zone, sizeof (zeros)))
2055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2056 zi->zone = zis_msg->zone;
2057 zi->has_zone = GNUNET_NO;
2061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2062 "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2063 zi->zone = zis_msg->zone;
2064 zi->has_zone = GNUNET_YES;
2066 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2067 run_zone_iteration_round (zi);
2068 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2073 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2076 * @param client GNUNET_SERVER_Client sending the message
2077 * @param message message of type 'struct ZoneIterationStopMessage'
2080 handle_iteration_stop (void *cls,
2081 struct GNUNET_SERVER_Client *client,
2082 const struct GNUNET_MessageHeader *message)
2084 struct GNUNET_NAMESTORE_Client *nc;
2085 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2086 const struct ZoneIterationStopMessage *zis_msg;
2089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2090 "Received `%s' message\n",
2091 "ZONE_ITERATION_STOP");
2092 if (NULL == (nc = client_lookup(client)))
2095 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2098 zis_msg = (const struct ZoneIterationStopMessage *) message;
2099 rid = ntohl (zis_msg->gns_header.r_id);
2100 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2101 if (zi->request_id == rid)
2106 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2109 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2110 if (GNUNET_YES == zi->has_zone)
2111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2112 "Stopped zone iteration for zone `%s'\n",
2113 GNUNET_short_h2s (&zi->zone));
2115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2116 "Stopped zone iteration over all zones\n");
2118 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2123 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT' message
2126 * @param client GNUNET_SERVER_Client sending the message
2127 * @param message message of type 'struct ZoneIterationNextMessage'
2130 handle_iteration_next (void *cls,
2131 struct GNUNET_SERVER_Client *client,
2132 const struct GNUNET_MessageHeader *message)
2134 struct GNUNET_NAMESTORE_Client *nc;
2135 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2136 const struct ZoneIterationNextMessage *zis_msg;
2139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2140 if (NULL == (nc = client_lookup(client)))
2143 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2146 zis_msg = (const struct ZoneIterationNextMessage *) message;
2147 rid = ntohl (zis_msg->gns_header.r_id);
2148 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2149 if (zi->request_id == rid)
2154 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2157 run_zone_iteration_round (zi);
2158 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2162 zonekey_it_key_cb (void *cls,
2163 struct GNUNET_CRYPTO_RsaPrivateKey *pk,
2166 struct KeyLoadContext *kl = cls;
2171 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2172 _("Could not parse zone key file `%s'\n"),
2176 learn_private_key (pk);
2179 GNUNET_CONTAINER_DLL_remove (kl_head, kl_tail, kl);
2180 GNUNET_free (kl->filename);
2186 * Load zone keys from directory by reading all .zkey files in this directory
2188 * @param cls int * 'counter' to store the number of files found
2189 * @param filename directory to scan
2190 * @return GNUNET_OK to continue
2193 zonekey_file_it (void *cls, const char *filename)
2195 struct KeyLoadContext *kl;
2197 if ((NULL == filename) ||
2198 (NULL == strstr(filename, ".zkey")))
2201 kl = GNUNET_malloc (sizeof (struct KeyLoadContext));
2202 kl->filename = strdup (filename);
2204 kl->keygen = GNUNET_CRYPTO_rsa_key_create_start (filename, zonekey_it_key_cb, kl);
2205 if (NULL == kl->keygen)
2207 GNUNET_free (kl->filename);
2212 GNUNET_CONTAINER_DLL_insert (kl_head, kl_tail, kl);
2218 * Process namestore requests.
2220 * @param cls closure
2221 * @param server the initialized server
2222 * @param cfg configuration to use
2225 run (void *cls, struct GNUNET_SERVER_Handle *server,
2226 const struct GNUNET_CONFIGURATION_Handle *cfg)
2228 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2229 {&handle_start, NULL,
2230 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2231 {&handle_lookup_name, NULL,
2232 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2233 {&handle_record_put, NULL,
2234 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2235 {&handle_record_create, NULL,
2236 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2237 {&handle_record_remove, NULL,
2238 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2239 {&handle_zone_to_name, NULL,
2240 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, sizeof (struct ZoneToNameMessage) },
2241 {&handle_iteration_start, NULL,
2242 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage) },
2243 {&handle_iteration_next, NULL,
2244 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, sizeof (struct ZoneIterationNextMessage) },
2245 {&handle_iteration_stop, NULL,
2246 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage) },
2250 unsigned int counter;
2252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2255 /* Load private keys from disk */
2257 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore",
2258 "zonefile_directory",
2259 &zonefile_directory))
2261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2262 _("No directory to load zonefiles specified in configuration\n"));
2263 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2267 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2269 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2271 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2272 _("Creating directory `%s' for zone files failed!\n"),
2273 zonefile_directory);
2274 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2278 "Created directory `%s' for zone files\n",
2279 zonefile_directory);
2282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2283 "Scanning directory `%s' for zone files\n", zonefile_directory);
2284 zonekeys = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
2286 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2288 "Found %u zone files\n",
2291 /* Loading database plugin */
2293 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2295 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2297 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2298 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2299 GNUNET_free (database);
2300 if (NULL == GSN_database)
2302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2303 "Could not load database backend `%s'\n",
2305 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2309 /* Configuring server handles */
2310 GNUNET_SERVER_add_handlers (server, handlers);
2311 snc = GNUNET_SERVER_notification_context_create (server, 16);
2312 GNUNET_SERVER_disconnect_notify (server,
2313 &client_disconnect_notification,
2315 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2321 * The main function for the template service.
2323 * @param argc number of arguments from the command line
2324 * @param argv command line arguments
2325 * @return 0 ok, 1 on error
2328 main (int argc, char *const *argv)
2330 return (GNUNET_OK ==
2331 GNUNET_SERVICE_run (argc, argv, "namestore",
2332 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2335 /* end of gnunet-service-namestore.c */