-more namestore code cleanup
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file namestore/gnunet-service-namestore.c
23  * @brief namestore for the GNUnet naming system
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
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"
33
34 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
35
36 /**
37  * A namestore operation.
38  */
39 struct GNUNET_NAMESTORE_ZoneIteration
40 {
41   /**
42    * Next element in the DLL
43    */
44   struct GNUNET_NAMESTORE_ZoneIteration *next;
45
46   /**
47    * Previous element in the DLL
48    */
49   struct GNUNET_NAMESTORE_ZoneIteration *prev;
50
51   /**
52    * Namestore client which intiated this zone iteration
53    */
54   struct GNUNET_NAMESTORE_Client *client;
55
56   /**
57    * GNUNET_YES if we iterate over a specific zone
58    * GNUNET_NO if we iterate over all zones
59    */
60   int has_zone;
61
62   /**
63    * Hash of the specific zone if 'has_zone' is GNUNET_YES,
64    * othwerwise set to '\0'
65    */
66   struct GNUNET_CRYPTO_ShortHashCode zone;
67
68   /**
69    * The operation id fot the zone iteration in the response for the client
70    */
71   uint64_t request_id;
72
73   /**
74    * Offset of the zone iteration used to address next result of the zone
75    * iteration in the store
76    *
77    * Initialy set to 0 in handle_iteration_start
78    * Incremented with by every call to handle_iteration_next
79    */
80   uint32_t offset;
81
82   /**
83    * Which flags must be included
84    */
85   uint16_t must_have_flags;
86
87   /**
88    * Which flags must not be included
89    */
90   uint16_t must_not_have_flags;
91 };
92
93
94 /**
95  * A namestore client
96  */
97 struct GNUNET_NAMESTORE_Client
98 {
99   /**
100    * Next element in the DLL
101    */
102   struct GNUNET_NAMESTORE_Client *next;
103
104   /**
105    * Previous element in the DLL
106    */
107   struct GNUNET_NAMESTORE_Client *prev;
108
109   /**
110    * The client
111    */
112   struct GNUNET_SERVER_Client *client;
113
114   /**
115    * Head of the DLL of
116    * Zone iteration operations in progress initiated by this client
117    */
118   struct GNUNET_NAMESTORE_ZoneIteration *op_head;
119
120   /**
121    * Tail of the DLL of
122    * Zone iteration operations in progress initiated by this client
123    */
124   struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
125 };
126
127
128 /**
129  * A container struct to store information belonging to a zone crypto key pair
130  */
131 struct GNUNET_NAMESTORE_CryptoContainer
132 {
133   /**
134    * Filename where to store the container
135    */
136   char *filename;
137
138   /**
139    * Short hash of the zone's public key
140    */
141   struct GNUNET_CRYPTO_ShortHashCode zone;
142
143   /**
144    * Zone's private key
145    */
146   struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
147
148   /**
149    * Zone's public key
150    */
151   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
152 };
153
154
155 /**
156  * Configuration handle.
157  */
158 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
159
160 /**
161  * Database handle
162  */
163 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
164
165 /**
166  * Zonefile directory
167  */
168 static char *zonefile_directory;
169
170 /**
171  * Name of the database plugin
172  */
173 static char *db_lib_name;
174
175 /**
176  * Our notification context.
177  */
178 static struct GNUNET_SERVER_NotificationContext *snc;
179
180 /**
181  * Head of the Client DLL
182  */
183 static struct GNUNET_NAMESTORE_Client *client_head;
184
185 /**
186  * Tail of the Client DLL
187  */
188 static struct GNUNET_NAMESTORE_Client *client_tail;
189
190 /**
191  * Hashmap containing the zone keys this namestore has is authoritative for
192  *
193  * Keys are the GNUNET_CRYPTO_HashCode of the GNUNET_CRYPTO_ShortHashCode
194  * The values are 'struct GNUNET_NAMESTORE_CryptoContainer *'
195  */
196 static struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
197
198
199 /**
200  * Writes the encrypted private key of a zone in a file
201  *
202  * @param filename where to store the zone
203  * @param c the crypto container containing private key of the zone
204  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
205  */
206 static int
207 write_key_to_file (const char *filename, 
208                    struct GNUNET_NAMESTORE_CryptoContainer *c)
209 {
210   struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
211   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
212   struct GNUNET_DISK_FileHandle *fd;
213   struct GNUNET_CRYPTO_ShortHashCode zone;
214   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
215   struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
216
217   fd = GNUNET_DISK_file_open (filename, 
218                               GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, 
219                               GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
220   if ( (NULL == fd) && (EEXIST == errno) )
221   {
222     privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
223     if (NULL == privkey)
224     {
225       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
226                   _("Failed to write zone key to file `%s': %s\n"),
227                   filename,
228                   _("file exists but reading key failed"));
229       return GNUNET_SYSERR;
230     }
231     GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
232     GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
233     GNUNET_CRYPTO_rsa_key_free (privkey);
234     if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
235     {
236       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
237                   "File zone `%s' containing this key already exists\n", 
238                   GNUNET_short_h2s (&zone));
239       return GNUNET_OK;
240     }
241     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
242                 _("Failed to write zone key to file `%s': %s\n"),
243                 filename,
244                 _("file exists with different key"));
245     return GNUNET_OK;    
246   }
247   if (NULL == fd)
248   {
249     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
250     return GNUNET_SYSERR;
251   }
252   if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
253   {
254     GNUNET_break (GNUNET_YES == GNUNET_DISK_file_close (fd));
255     return GNUNET_SYSERR;
256   }
257   enc = GNUNET_CRYPTO_rsa_encode_key (ret);
258   GNUNET_assert (NULL != enc);
259   GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
260   GNUNET_free (enc);
261   GNUNET_DISK_file_sync (fd);
262   if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
263     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
264   GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
265   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
266               "Stored zonekey for zone `%s' in file `%s'\n",
267               GNUNET_short_h2s(&c->zone), c->filename);
268   return GNUNET_OK;
269 }
270
271
272 /**
273  * Write allthe given zone key to disk and then removes the entry from the
274  * 'zonekeys' hash map.
275  *
276  * @param cls unused
277  * @param key zone key
278  * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
279  *        key
280  * @return GNUNET_OK to continue iteration
281  */
282 static int
283 zone_to_disk_it (void *cls,
284                  const struct GNUNET_HashCode *key,
285                  void *value)
286 {
287   struct GNUNET_NAMESTORE_CryptoContainer *c = value;
288
289   if (NULL == c->filename)
290     GNUNET_asprintf(&c->filename, 
291                     "%s/%s.zkey", 
292                     zonefile_directory, 
293                     GNUNET_short_h2s (&c->zone));
294   (void) write_key_to_file(c->filename, c);
295   GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
296   GNUNET_CRYPTO_rsa_key_free (c->privkey);
297   GNUNET_free (c->pubkey);
298   GNUNET_free (c->filename);
299   GNUNET_free (c);
300   return GNUNET_OK;
301 }
302
303
304 /**
305  * Returns the expiration time of the given block of records. The block
306  * expiration time is the expiration time of the block with smallest
307  * expiration time.
308  *
309  * @param rd_count number of records given in 'rd'
310  * @param rd array of records
311  * @return absolute expiration time
312  */
313 static struct GNUNET_TIME_Absolute
314 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
315 {
316   unsigned int c;
317   struct GNUNET_TIME_Absolute expire;
318   struct GNUNET_TIME_Absolute at;
319   struct GNUNET_TIME_Relative rt;
320
321   if (NULL == rd)
322     return GNUNET_TIME_UNIT_ZERO_ABS;
323   expire = GNUNET_TIME_UNIT_FOREVER_ABS;
324   for (c = 0; c < rd_count; c++)  
325   {
326     if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
327     {
328       rt.rel_value = rd[c].expiration_time;
329       at = GNUNET_TIME_relative_to_absolute (rt);
330     }
331     else
332     {
333       at.abs_value = rd[c].expiration_time;
334     }
335     expire = GNUNET_TIME_absolute_min (at, expire);  
336   }
337   return expire;
338 }
339
340
341 /**
342  * Task run during shutdown.
343  *
344  * @param cls unused
345  * @param tc unused
346  */
347 static void
348 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
349 {
350   struct GNUNET_NAMESTORE_ZoneIteration *no;
351   struct GNUNET_NAMESTORE_Client *nc;
352
353   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
354   if (NULL != snc)
355   {
356     GNUNET_SERVER_notification_context_destroy (snc);
357     snc = NULL;
358   }
359   GNUNET_CONTAINER_multihashmap_iterate (zonekeys, &zone_to_disk_it, NULL);
360   GNUNET_CONTAINER_multihashmap_destroy (zonekeys);
361   zonekeys = NULL;
362   while (NULL != (nc = client_head))
363   {
364     while (NULL != (no = nc->op_head))
365     {
366       GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
367       GNUNET_free (no);
368     }
369     GNUNET_SERVER_client_drop(nc->client);
370     GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
371     GNUNET_free (nc);
372   }
373   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
374   GNUNET_free (db_lib_name);
375   db_lib_name = NULL;
376   GNUNET_free_non_null (zonefile_directory);
377   zonefile_directory = NULL;
378 }
379
380
381 /**
382  * Lookup our internal data structure for a given client.
383  *
384  * @param client server client handle to use for the lookup
385  * @return our internal structure for the client, NULL if
386  *         we do not have any yet
387  */
388 static struct GNUNET_NAMESTORE_Client *
389 client_lookup (struct GNUNET_SERVER_Client *client)
390 {
391   struct GNUNET_NAMESTORE_Client *nc;
392
393   GNUNET_assert (NULL != client);
394   for (nc = client_head; NULL != nc; nc = nc->next)  
395     if (client == nc->client)
396       return nc;  
397   return NULL;
398 }
399
400
401 /**
402  * Called whenever a client is disconnected.
403  * Frees our resources associated with that client.
404  *
405  * @param cls closure
406  * @param client identification of the client
407  */
408 static void
409 client_disconnect_notification (void *cls, 
410                                 struct GNUNET_SERVER_Client *client)
411 {
412   struct GNUNET_NAMESTORE_ZoneIteration *no;
413   struct GNUNET_NAMESTORE_Client *nc;
414
415   if (NULL == client)
416     return;
417   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
418               "Client %p disconnected\n", 
419               client);
420   nc = client_lookup (client);
421   if (NULL == nc)
422     return;
423   while (NULL != (no = nc->op_head))
424   {
425     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
426     GNUNET_free (no);
427   }
428   GNUNET_SERVER_client_drop (nc->client);
429   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
430   GNUNET_free (nc);
431 }
432
433
434 /**
435  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
436  *
437  * @param cls unused
438  * @param client GNUNET_SERVER_Client sending the message
439  * @param message unused
440  */
441 static void
442 handle_start (void *cls,
443               struct GNUNET_SERVER_Client *client,
444               const struct GNUNET_MessageHeader *message)
445 {
446   struct GNUNET_NAMESTORE_Client *nc;
447
448   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
449               "Client %p connected\n", client);
450   if (NULL != client_lookup (client))
451   {
452     GNUNET_break (0);
453     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
454     return;
455   }
456   nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
457   nc->client = client;
458   GNUNET_SERVER_notification_context_add (snc, client);
459   GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc);
460   GNUNET_SERVER_client_keep (client);
461   GNUNET_SERVER_receive_done (client, GNUNET_OK);
462 }
463
464
465 /**
466  * Context for name lookups passed from 'handle_lookup_name' to
467  * 'handle_lookup_name_it' as closure
468  */
469 struct LookupNameContext
470 {
471   /**
472    * The client to send the response to
473    */
474   struct GNUNET_NAMESTORE_Client *nc;
475
476   /**
477    * Requested zone
478    */
479   const struct GNUNET_CRYPTO_ShortHashCode *zone;
480
481   /**
482    * Requested name
483    */
484   const char *name;
485
486   /**
487    * Operation id for the name lookup
488    */
489   uint32_t request_id;
490
491   /**
492    * Requested specific record type
493    */
494   uint32_t record_type;
495 };
496
497
498 /**
499  * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
500  *
501  * @param cls a 'struct LookupNameContext *' with information about the request
502  * @param zone_key zone key of the zone
503  * @param expire expiration time
504  * @param name name
505  * @param rd_count number of records
506  * @param rd array of records
507  * @param signature signature
508  */
509 static void
510 handle_lookup_name_it (void *cls,
511                        const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
512                        struct GNUNET_TIME_Absolute expire,
513                        const char *name,
514                        unsigned int rd_count,
515                        const struct GNUNET_NAMESTORE_RecordData *rd,
516                        const struct GNUNET_CRYPTO_RsaSignature *signature)
517 {
518   struct LookupNameContext *lnc = cls;
519   struct LookupNameResponseMessage *lnr_msg;
520   struct GNUNET_NAMESTORE_RecordData *rd_selected;
521   struct GNUNET_NAMESTORE_CryptoContainer *cc;
522   struct GNUNET_CRYPTO_RsaSignature *signature_new;
523   struct GNUNET_TIME_Absolute e;
524   struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
525   struct GNUNET_HashCode long_hash;
526   char *rd_tmp;
527   char *name_tmp;
528   size_t rd_ser_len;
529   size_t r_size;
530   size_t name_len;
531   int copied_elements;
532   int contains_signature;
533   int authoritative;
534   int c;
535
536   name_len = (NULL == name) ? 0 : strlen(name) + 1;
537   copied_elements = 0;
538   rd_selected = NULL;
539   /* count records to copy */
540   if (0 != lnc->record_type)
541   {
542     /* special record type needed */
543     for (c = 0; c < rd_count; c++)
544       if (rd[c].record_type == lnc->record_type)
545         copied_elements++; /* found matching record */
546     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
547                 "Found %u records with type %u for name `%s' in zone `%s'\n",
548                 copied_elements, 
549                 lnc->record_type, 
550                 lnc->name, 
551                 GNUNET_short_h2s(lnc->zone));
552     if (copied_elements > 0)
553     {
554       rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
555       copied_elements = 0;
556       for (c = 0; c < rd_count; c++)
557       {
558         if (rd[c].record_type == lnc->record_type)
559         {
560           /* found matching record */
561           rd_selected[copied_elements] = rd[c]; /* shallow copy! */
562           copied_elements++;
563         }
564       }
565     }
566   }
567   else
568   {
569     copied_elements = rd_count;
570     rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
571   }
572   // FIXME: need to adjust 'rd' from relative to absolute times!
573   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
574               "Found %u records for name `%s' in zone `%s'\n",
575               copied_elements,
576               lnc->name, 
577               GNUNET_short_h2s (lnc->zone));
578
579   if ((copied_elements == rd_count) && (NULL != signature))
580     contains_signature = GNUNET_YES; /* returning all records, so include signature */
581   else
582     contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
583
584   authoritative = GNUNET_NO;
585   signature_new = NULL;
586   if ((NULL != zone_key) && (copied_elements == rd_count))
587   {
588     GNUNET_CRYPTO_short_hash (zone_key, 
589                               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), 
590                               &zone_key_hash);
591     GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
592     if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash)))
593     {
594       e = get_block_expiration_time (rd_count, rd);
595       signature_new = GNUNET_NAMESTORE_create_signature (cc->privkey, e, name, rd, rd_count);
596       GNUNET_assert (NULL != signature_new);
597       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
598                   "Creating signature for name `%s' with %u records in zone `%s'\n",
599                   name, 
600                   copied_elements,
601                   GNUNET_short_h2s(&zone_key_hash));
602       authoritative = GNUNET_YES;
603     }
604   }
605
606   rd_ser_len = GNUNET_NAMESTORE_records_get_size (copied_elements, rd_selected);
607   r_size = sizeof (struct LookupNameResponseMessage) +
608            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
609            name_len +
610            rd_ser_len;
611   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
612               "Sending `%s' message\n", 
613               "NAMESTORE_LOOKUP_NAME_RESPONSE");
614   lnr_msg = GNUNET_malloc (r_size);
615   lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
616   lnr_msg->gns_header.header.size = ntohs (r_size);
617   lnr_msg->gns_header.r_id = htonl (lnc->request_id);
618   lnr_msg->rd_count = htons (copied_elements);
619   lnr_msg->rd_len = htons (rd_ser_len);
620   lnr_msg->name_len = htons (name_len);
621   lnr_msg->expire = GNUNET_TIME_absolute_hton (get_block_expiration_time (copied_elements, 
622                                                                           rd_selected));
623   name_tmp = (char *) &lnr_msg[1];
624   memcpy (name_tmp, name, name_len);
625   rd_tmp = &name_tmp[name_len];
626   GNUNET_NAMESTORE_records_serialize (copied_elements, rd_selected, rd_ser_len, rd_tmp);
627
628   if (rd_selected != rd)
629     GNUNET_free_non_null (rd_selected);
630
631   if (NULL != zone_key)
632     lnr_msg->public_key = *zone_key;
633   if (GNUNET_YES == authoritative)
634   {
635     /* use new created signature */
636     lnr_msg->contains_sig = htons (GNUNET_YES);
637     GNUNET_assert (NULL != signature_new);
638     lnr_msg->signature = *signature_new;
639     GNUNET_free (signature_new);
640   }
641   else if (GNUNET_YES == contains_signature)
642   {
643     /* use existing signature */
644     lnr_msg->contains_sig = htons (GNUNET_YES);
645     GNUNET_assert (NULL != signature);
646     lnr_msg->signature = *signature;
647   }
648   GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, 
649                                               &lnr_msg->gns_header.header, 
650                                               GNUNET_NO);
651   GNUNET_free (lnr_msg);
652 }
653
654
655 /**
656  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
657  *
658  * @param cls unused
659  * @param client GNUNET_SERVER_Client sending the message
660  * @param message message of type 'struct LookupNameMessage'
661  */
662 static void
663 handle_lookup_name (void *cls,
664                     struct GNUNET_SERVER_Client *client,
665                     const struct GNUNET_MessageHeader *message)
666 {
667   const struct LookupNameMessage *ln_msg;
668   struct LookupNameContext lnc;
669   struct GNUNET_NAMESTORE_Client *nc;
670   size_t name_len;
671   const char *name;
672   uint32_t rid;
673   uint32_t type;
674
675   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
676               "Received `%s' message\n", 
677               "NAMESTORE_LOOKUP_NAME");
678   if (ntohs (message->size) < sizeof (struct LookupNameMessage))
679   {
680     GNUNET_break (0);
681     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
682     return;
683   }
684   if (NULL == (nc = client_lookup(client)))
685   {
686     GNUNET_break (0);
687     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
688     return;
689   }
690   ln_msg = (const struct LookupNameMessage *) message;
691   rid = ntohl (ln_msg->gns_header.r_id);
692   name_len = ntohl (ln_msg->name_len);
693   type = ntohl (ln_msg->record_type);
694   if ((0 == name_len) || (name_len > MAX_NAME_LEN))
695   {
696     GNUNET_break (0);
697     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
698     return;
699   }
700   name = (const char *) &ln_msg[1];
701   if (name[name_len -1] != '\0')
702   {
703     GNUNET_break (0);
704     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
705     return;
706   }
707   if (GNUNET_NAMESTORE_TYPE_ANY == type)
708     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
709                 "Looking up all records for name `%s' in zone `%s'\n", 
710                 name, 
711                 GNUNET_short_h2s(&ln_msg->zone));
712   else
713     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
714                 "Looking up records with type %u for name `%s' in zone `%s'\n", 
715                 type, name, 
716                 GNUNET_short_h2s(&ln_msg->zone));
717
718   /* do the actual lookup */
719   lnc.request_id = rid;
720   lnc.nc = nc;
721   lnc.record_type = type;
722   lnc.name = name;
723   lnc.zone = &ln_msg->zone;
724   if (GNUNET_SYSERR ==
725       GSN_database->iterate_records (GSN_database->cls, 
726                                      &ln_msg->zone, name, 0 /* offset */, 
727                                      &handle_lookup_name_it, &lnc))
728   {
729     /* internal error (in database plugin); might be best to just hang up on
730        plugin rather than to signal that there are 'no' results, which 
731        might also be false... */
732     GNUNET_break (0); 
733     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
734     return;
735   }
736   GNUNET_SERVER_receive_done (client, GNUNET_OK);
737 }
738
739
740 /**
741  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
742  *
743  * @param cls unused
744  * @param client GNUNET_SERVER_Client sending the message
745  * @param message message of type 'struct RecordPutMessage'
746  */
747 static void
748 handle_record_put (void *cls,
749                    struct GNUNET_SERVER_Client *client,
750                    const struct GNUNET_MessageHeader *message)
751 {
752   struct GNUNET_NAMESTORE_Client *nc;
753   const struct RecordPutMessage *rp_msg;
754   struct GNUNET_TIME_Absolute expire;
755   const struct GNUNET_CRYPTO_RsaSignature *signature;
756   struct RecordPutResponseMessage rpr_msg;
757   struct GNUNET_CRYPTO_ShortHashCode zone_hash;
758   size_t name_len;
759   size_t msg_size;
760   size_t msg_size_exp;
761   const char *name;
762   const char *rd_ser;
763   uint32_t rid;
764   uint32_t rd_ser_len;
765   uint32_t rd_count;
766   int res;
767
768   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
769               "Received `%s' message\n",
770               "NAMESTORE_RECORD_PUT");
771   if (ntohs (message->size) < sizeof (struct RecordPutMessage))
772   {
773     GNUNET_break (0);
774     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
775     return;
776   }
777   if (NULL == (nc = client_lookup (client)))
778   {
779     GNUNET_break (0);
780     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
781     return;
782   }
783   rp_msg = (const struct RecordPutMessage *) message;
784   rid = ntohl (rp_msg->gns_header.r_id);
785   msg_size = ntohs (rp_msg->gns_header.header.size);
786   name_len = ntohs (rp_msg->name_len);
787   rd_count = ntohs (rp_msg->rd_count);
788   rd_ser_len = ntohs (rp_msg->rd_len);
789   if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >= MAX_NAME_LEN) || (0 == name_len))
790   {
791     GNUNET_break (0);
792     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
793     return;
794   }
795   msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
796   if (msg_size != msg_size_exp)
797   {
798     GNUNET_break (0);
799     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
800     return;
801   }
802   name = (const char *) &rp_msg[1];
803   if ('\0' != name[name_len -1])
804   {
805     GNUNET_break (0);
806     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
807     return;
808   }
809   expire = GNUNET_TIME_absolute_ntoh (rp_msg->expire);
810   signature = &rp_msg->signature;
811   rd_ser = &name[name_len];
812   {
813     struct GNUNET_NAMESTORE_RecordData rd[rd_count];
814
815     if (GNUNET_OK !=
816         GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd))
817     {
818       GNUNET_break (0);
819       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
820       return;
821     }
822     GNUNET_CRYPTO_short_hash (&rp_msg->public_key, 
823                               sizeof (rp_msg->public_key), 
824                               &zone_hash);
825     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
826                 "Putting %u records under name `%s' in zone `%s'\n",
827                 rd_count, name,
828                 GNUNET_short_h2s (&zone_hash));
829     res = GSN_database->put_records(GSN_database->cls,
830                                     &rp_msg->public_key,
831                                     expire,
832                                     name,
833                                     rd_count, rd,
834                                     signature);
835     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
836                 "Putting record for name `%s': %s\n",
837                 name, 
838                 (res == GNUNET_OK) ? "OK" : "FAILED");
839   }
840   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
841               "Sending `%s' message\n", 
842               "RECORD_PUT_RESPONSE");
843   rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
844   rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
845   rpr_msg.gns_header.r_id = htonl (rid);
846   rpr_msg.op_result = htonl (res);
847   GNUNET_SERVER_notification_context_unicast (snc, 
848                                               nc->client, 
849                                               &rpr_msg.gns_header.header, 
850                                               GNUNET_NO);
851   GNUNET_SERVER_receive_done (client, GNUNET_OK);
852 }
853
854
855 /////////////////////////////////////////////////////////////
856
857
858 /**
859  * Context for record create operations passed from 'handle_record_create' to
860  * 'handle_create_record_it' as closure
861  */
862 struct CreateRecordContext
863 {
864   /**
865    * Record data
866    */
867   const struct GNUNET_NAMESTORE_RecordData *rd;
868
869   /**
870    * Zone's private key
871    */
872   const struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
873
874   /**
875    * Zone's public key
876    */
877   const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
878
879   /**
880    * Name for the record to create
881    */
882   const char *name;
883
884   /**
885    * Record expiration time
886    */
887   struct GNUNET_TIME_Absolute expire;
888
889   /**
890    * result returned from 'handle_create_record_it'
891    * GNUNET_SYSERR: failed to create the record
892    * GNUNET_NO: we updated an existing record or identical entry existed
893    * GNUNET_YES : we created a new record
894    */
895   int res;
896 };
897
898
899 /**
900  * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
901  * in handle_record_create
902  *
903  * @param cls a 'struct CreateRecordContext *' with information about the request
904  * @param pubkey zone key of the zone
905  * @param expire expiration time
906  * @param name name
907  * @param rd_count number of records
908  * @param rd array of records
909  * @param signature signature
910  */
911 static void
912 handle_create_record_it (void *cls,
913                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
914                          struct GNUNET_TIME_Absolute expire,
915                          const char *name,
916                          unsigned int rd_count,
917                          const struct GNUNET_NAMESTORE_RecordData *rd,
918                          const struct GNUNET_CRYPTO_RsaSignature *signature)
919 {
920   struct CreateRecordContext *crc = cls;
921   struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
922   struct GNUNET_CRYPTO_RsaSignature dummy_signature;
923   struct GNUNET_TIME_Absolute block_expiration;
924   int res;
925   int exist = GNUNET_SYSERR;
926   int update = GNUNET_NO;
927   int c;
928   int rd_count_new = 0;
929
930   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
931               "Found %u existing records for `%s'\n", 
932               rd_count, crc->name);
933   for (c = 0; c < rd_count; c++)
934   {
935     if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) && 
936          (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
937     {
938       /* Update unique PKEY */
939       exist = c;
940       update = GNUNET_YES;
941       break;
942     }
943     if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) && 
944          (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
945     {
946       /* Update unique PSEU */
947       exist = c;
948       update = GNUNET_YES;
949       break;
950     }
951     if ((crc->rd->record_type == rd[c].record_type) &&
952         (crc->rd->data_size == rd[c].data_size) &&
953         (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
954     {
955       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
956                   "Found existing records for `%s' to update expiration date!\n",
957                   crc->name);
958       exist = c;
959       if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
960            ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) 
961             == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
962         update = GNUNET_YES;
963       break;
964     }
965   }
966
967   if (exist == GNUNET_SYSERR)
968   {
969     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
970                 "No existing record for name `%s'!\n", 
971                 crc->name);
972     rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
973     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
974     rd_count_new = rd_count + 1;
975     rd_new[rd_count] = *(crc->rd);
976   }
977   else if (update == GNUNET_NO)
978   {
979     /* Exact same record already exists */
980     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
981                 "Matching record for %s' exists, no change required!\n",
982                 crc->name);
983     res = GNUNET_NO;
984     goto end;
985   }
986   else 
987   {
988     /* Update record */
989     GNUNET_assert (GNUNET_YES == update);
990     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
991                 "Updating existing records for `%s'!\n", 
992                 crc->name);
993     rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
994     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
995     rd_count_new = rd_count;
996     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
997                 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) 
998                 ? "Updating absolute expiration from %llu to %llu!\n"
999                 : "Updating relative expiration from %llu to %llu!\n", 
1000                 rd_new[exist].expiration_time, crc->rd->expiration_time);
1001     rd_new[exist] = *(crc->rd);
1002   }
1003
1004   block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
1005   if (block_expiration.abs_value != expire.abs_value)
1006     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1007                 "Updated block expiration time\n");
1008
1009   memset (&dummy_signature, '\0', sizeof (dummy_signature));
1010
1011   /* Database operation */
1012   GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
1013   res = GSN_database->put_records(GSN_database->cls,
1014                                 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
1015                                 block_expiration,
1016                                 crc->name,
1017                                 rd_count_new, rd_new,
1018                                 &dummy_signature);
1019   GNUNET_break (GNUNET_OK == res);
1020   if (res == GNUNET_OK)
1021     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
1022   else
1023     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
1024   res = GNUNET_YES;
1025
1026 end:
1027   GNUNET_free_non_null (rd_new);
1028
1029   switch (res) {
1030     case GNUNET_SYSERR:
1031        /* failed to create the record */
1032        crc->res = GNUNET_SYSERR;
1033       break;
1034     case GNUNET_YES:
1035       /* database operations OK */
1036       if (GNUNET_YES == update)
1037       {
1038         /* we updated an existing record */
1039         crc->res = GNUNET_NO;
1040       }
1041       else
1042       {
1043         /* we created a new record */
1044         crc->res = GNUNET_YES;
1045       }
1046       break;
1047     case GNUNET_NO:
1048         /* identical entry existed, so we did nothing */
1049         crc->res = GNUNET_NO;
1050       break;
1051     default:
1052       break;
1053   }
1054   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
1055 }
1056
1057
1058 /**
1059  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1060  *
1061  * @param cls unused
1062  * @param client GNUNET_SERVER_Client sending the message
1063  * @param message message of type 'struct RecordCreateMessage'
1064  */
1065 static void
1066 handle_record_create (void *cls,
1067                       struct GNUNET_SERVER_Client *client,
1068                       const struct GNUNET_MessageHeader *message)
1069 {
1070   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1071   struct GNUNET_NAMESTORE_Client *nc;
1072   struct RecordCreateMessage *rp_msg;
1073   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1074   struct CreateRecordContext crc;
1075   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1076   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1077   struct RecordCreateResponseMessage rcr_msg;
1078   struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1079   struct GNUNET_HashCode long_hash;
1080   size_t name_len;
1081   size_t msg_size;
1082   size_t msg_size_exp;
1083   size_t rd_ser_len;
1084   size_t key_len;
1085   uint32_t rid = 0;
1086   char *pkey_tmp;
1087   char *name_tmp;
1088   char *rd_ser;
1089   int rd_count;
1090
1091   int res = GNUNET_SYSERR;
1092   crc.res = GNUNET_SYSERR;
1093
1094   if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1095   {
1096     GNUNET_break_op (0);
1097     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1098     return;
1099   }
1100
1101   nc = client_lookup(client);
1102   if (nc == NULL)
1103   {
1104     GNUNET_break_op (0);
1105     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1106     return;
1107   }
1108
1109   rp_msg = (struct RecordCreateMessage *) message;
1110   rid = ntohl (rp_msg->gns_header.r_id);
1111   name_len = ntohs (rp_msg->name_len);
1112   msg_size = ntohs (message->size);
1113   rd_count = ntohs (rp_msg->rd_count);
1114   rd_ser_len = ntohs (rp_msg->rd_len);
1115   key_len = ntohs (rp_msg->pkey_len);
1116   msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1117
1118   if (msg_size != msg_size_exp)
1119   {
1120     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1121     GNUNET_break_op (0);
1122     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1123     return;
1124   }
1125
1126   if ((name_len == 0) || (name_len > MAX_NAME_LEN))
1127   {
1128     GNUNET_break_op (0);
1129     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1130     return;
1131   }
1132
1133   pkey_tmp = (char *) &rp_msg[1];
1134   name_tmp = &pkey_tmp[key_len];
1135   rd_ser = &name_tmp[name_len];
1136
1137   if (name_tmp[name_len -1] != '\0')
1138   {
1139     GNUNET_break_op (0);
1140     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1141     return;
1142   }
1143
1144   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1145
1146   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1147   if ((res != GNUNET_OK) || (rd_count != 1))
1148   {
1149     GNUNET_break_op (0);
1150     goto send;
1151   }
1152   /* Extracting and converting private key */
1153   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1154   GNUNET_assert (pkey != NULL);
1155   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1156   GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1157   GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1158
1159   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1160   {
1161     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash));
1162
1163     cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1164     cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1165     cc->pubkey = GNUNET_malloc(sizeof (pub));
1166     memcpy (cc->pubkey, &pub, sizeof(pub));
1167     cc->zone = pubkey_hash;
1168     GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1169   }
1170
1171   crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1172   crc.res = GNUNET_SYSERR;
1173   crc.pkey = pkey;
1174   crc.pubkey = &pub;
1175   crc.rd = rd;
1176   crc.name = name_tmp;
1177
1178   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1179
1180   /* Get existing records for name */
1181   res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
1182   if (res != GNUNET_SYSERR)
1183     res = GNUNET_OK;
1184   GNUNET_CRYPTO_rsa_key_free(pkey);
1185   pkey = NULL;
1186
1187   /* Send response */
1188 send:
1189   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1190   rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1191   rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1192   rcr_msg.gns_header.r_id = htonl (rid);
1193   if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1194     rcr_msg.op_result = htonl (GNUNET_YES);
1195   else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1196     rcr_msg.op_result = htonl (GNUNET_NO);
1197   else
1198     rcr_msg.op_result = htonl (GNUNET_SYSERR);
1199   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
1200
1201   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1202 }
1203
1204
1205 /**
1206  * RemoveRecordContext
1207  *
1208  * Context for record remove operations passed from 'handle_record_remove' to
1209  * 'handle_record_remove_it' as closure
1210  */
1211 struct RemoveRecordContext
1212 {
1213   /**
1214    * Record to remove
1215    */
1216   struct GNUNET_NAMESTORE_RecordData *rd;
1217
1218   /**
1219    * Zone's private keys
1220    */
1221   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1222
1223   /**
1224    * Name to remove
1225    */
1226   int remove_name;
1227
1228   /**
1229    * 0 : Success
1230    * 1 : Could not find record to remove, empty result set
1231    * 2 : Could not find record to remove, record did not exist in result set
1232    * 3 : Could not remove records from database
1233    * 4 : Could not put records into database
1234    */
1235   uint16_t op_res;
1236 };
1237
1238
1239 /**
1240  * FIXME...
1241  */
1242 static void
1243 handle_record_remove_it (void *cls,
1244     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1245     struct GNUNET_TIME_Absolute expire,
1246     const char *name,
1247     unsigned int rd_count,
1248     const struct GNUNET_NAMESTORE_RecordData *rd,
1249     const struct GNUNET_CRYPTO_RsaSignature *signature)
1250 {
1251   struct RemoveRecordContext *rrc = cls;
1252   unsigned int c;
1253   int res;
1254   int found;
1255   unsigned int rd_count_new;
1256
1257   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
1258
1259   if (rd_count == 0)
1260   {
1261     /* Could not find record to remove */
1262     rrc->op_res = 1;
1263     return;
1264   }
1265
1266   /* Find record to remove */
1267   found = GNUNET_SYSERR;
1268   for (c = 0; c < rd_count; c++)
1269   {
1270     /*
1271     if (rd[c].flags != rrc->rd->flags)
1272        continue;*/
1273     if (rd[c].record_type != rrc->rd->record_type)
1274        continue;
1275     /*
1276     if (rd[c].data_size != rrc->rd->data_size)
1277        continue;
1278     GNUNET_break(0);
1279     if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1280         continue;
1281     GNUNET_break(0); */
1282     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1283     found = c;
1284     break;
1285   }
1286   if (GNUNET_SYSERR == found)
1287   {
1288     /* Could not find record to remove */
1289     rrc->op_res = 2;
1290     return;
1291   }
1292
1293   if (rd_count-1 == 0)
1294   {
1295     struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1296     GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1297     res = GSN_database->remove_records (GSN_database->cls,
1298                                         &pubkey_hash,
1299                                         name);
1300     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1301                 "No records left for name `%s', removing name\n",
1302                 name, res);
1303     if (GNUNET_OK != res)
1304     {
1305       /* Could not remove records from database */
1306       rrc->op_res = 3;
1307       return;
1308     }
1309     rrc->op_res = 0;
1310     return;
1311   }
1312
1313   rd_count_new = rd_count -1;
1314   struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1315
1316   unsigned int c2 = 0;
1317   for (c = 0; c < rd_count; c++)
1318   {
1319     if (c != found)
1320     {
1321       GNUNET_assert (c2 < rd_count_new);
1322       rd_new[c2] = rd[c];
1323       c2++;
1324     }
1325   }
1326
1327   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1328
1329   /* Create dummy signature */
1330   struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1331   memset (&dummy_signature, '\0', sizeof (dummy_signature));
1332
1333
1334   /* Put records */
1335   res = GSN_database->put_records(GSN_database->cls,
1336                                   zone_key,
1337                                   expire,
1338                                   name,
1339                                   rd_count_new, rd_new,
1340                                   &dummy_signature);
1341   if (GNUNET_OK != res)
1342   {
1343     /* Could not put records into database */
1344     rrc->op_res = 4;
1345     return;
1346   }
1347
1348   rrc->op_res = 0;
1349 }
1350
1351
1352 /**
1353  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1354  *
1355  * @param cls unused
1356  * @param client GNUNET_SERVER_Client sending the message
1357  * @param message message of type 'struct RecordRemoveMessage'
1358  */
1359 static void
1360 handle_record_remove (void *cls,
1361                       struct GNUNET_SERVER_Client *client,
1362                       const struct GNUNET_MessageHeader *message)
1363 {
1364   struct GNUNET_NAMESTORE_Client *nc;
1365   const struct RecordRemoveMessage *rr_msg;
1366   struct RecordRemoveResponseMessage rrr_msg;
1367   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1368   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1369   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1370   struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1371   struct GNUNET_HashCode long_hash;
1372   const char *pkey_tmp;
1373   const char *name_tmp;
1374   const char *rd_ser;
1375   size_t key_len;
1376   size_t name_len;
1377   size_t rd_ser_len;
1378   size_t msg_size;
1379   size_t msg_size_exp = 0;
1380   uint32_t rd_count;
1381   uint32_t rid;
1382
1383   int res = GNUNET_SYSERR;
1384
1385   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1386   if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1387   {
1388     GNUNET_break_op (0);
1389     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1390     return;
1391   }
1392
1393   nc = client_lookup(client);
1394   if (nc == NULL)
1395   {
1396     GNUNET_break_op (0);
1397     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1398     return;
1399   }
1400
1401   rr_msg = (const struct RecordRemoveMessage *) message;
1402   rid = ntohl (rr_msg->gns_header.r_id);
1403   name_len = ntohs (rr_msg->name_len);
1404   rd_ser_len = ntohs (rr_msg->rd_len);
1405   rd_count = ntohs (rr_msg->rd_count);
1406   key_len = ntohs (rr_msg->pkey_len);
1407   msg_size = ntohs (message->size);
1408
1409   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1410   {
1411     GNUNET_break_op (0);
1412     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1413     return;
1414   }
1415
1416   if ((name_len >=MAX_NAME_LEN) || (name_len == 0))
1417   {
1418     GNUNET_break_op (0);
1419     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1420     return;
1421   }
1422
1423   msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1424   if (msg_size != msg_size_exp)
1425   {
1426     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1427     GNUNET_break_op (0);
1428     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1429     return;
1430   }
1431
1432   pkey_tmp = (const char *) &rr_msg[1];
1433   name_tmp = &pkey_tmp[key_len];
1434   rd_ser = &name_tmp[name_len];
1435
1436
1437   if ((name_len == 0) || (name_len > MAX_NAME_LEN))
1438   {
1439     GNUNET_break_op (0);
1440     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1441     return;
1442   }
1443
1444   if (name_tmp[name_len -1] != '\0')
1445   {
1446     GNUNET_break_op (0);
1447     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1448     return;
1449   }
1450
1451   /* Extracting and converting private key */
1452   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1453   GNUNET_assert (pkey != NULL);
1454   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1455   GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1456   GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1457
1458   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1459   {
1460     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1461                 "Received new private key for zone `%s'\n",
1462                 GNUNET_short_h2s(&pubkey_hash));
1463     cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1464     cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1465     cc->pubkey = GNUNET_malloc(sizeof (pub));
1466     memcpy (cc->pubkey, &pub, sizeof(pub));
1467     cc->zone = pubkey_hash;
1468
1469     GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1470   }
1471
1472
1473   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1474   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1475   if ((res != GNUNET_OK) || (rd_count > 1))
1476   {
1477     GNUNET_break_op (0);
1478     goto send;
1479   }
1480
1481   if (0 == rd_count)
1482   {
1483     /* remove the whole name and all records */
1484     /* Database operation */
1485     res = GSN_database->remove_records (GSN_database->cls,
1486                                          &pubkey_hash,
1487                                          name_tmp);
1488     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1489         name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1490
1491     if (GNUNET_OK != res)
1492       /* Could not remove entry from database */
1493       res = 4;
1494     else
1495       res = 0;
1496   }
1497   else
1498   {
1499     /* remove a single record */
1500     struct RemoveRecordContext rrc;
1501     rrc.rd = rd;
1502     rrc.pkey = pkey;
1503
1504     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1505
1506     /* Database operation */
1507     res = GSN_database->iterate_records (GSN_database->cls,
1508                                          &pubkey_hash,
1509                                          name_tmp,
1510                                          0,
1511                                          handle_record_remove_it, &rrc);
1512
1513     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1514         name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1515     res = rrc.op_res;
1516   }
1517   /* Send response */
1518 send:
1519   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1520   rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1521   rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1522   rrr_msg.gns_header.r_id = htonl (rid);
1523   rrr_msg.op_result = htonl (res);
1524   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1525
1526   GNUNET_CRYPTO_rsa_key_free (pkey);
1527
1528   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1529 }
1530
1531 /**
1532  * ZoneToNameCtx
1533  *
1534  * Context for record remove operations passed from 'handle_zone_to_name' to
1535  * 'handle_zone_to_name_it' as closure
1536  */
1537 struct ZoneToNameCtx
1538 {
1539   /**
1540    * Namestore client
1541    */
1542   struct GNUNET_NAMESTORE_Client *nc;
1543
1544   /**
1545    * Request id
1546    */
1547   uint32_t rid;
1548 };
1549
1550
1551 /**
1552  * Zone to name iterator
1553  *
1554  * @param cls struct ZoneToNameCtx *
1555  * @param zone_key the zone key
1556  * @param expire expiration date
1557  * @param name name
1558  * @param rd_count number of records
1559  * @param rd record data
1560  * @param signature signature
1561  */
1562 static void
1563 handle_zone_to_name_it (void *cls,
1564     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1565     struct GNUNET_TIME_Absolute expire,
1566     const char *name,
1567     unsigned int rd_count,
1568     const struct GNUNET_NAMESTORE_RecordData *rd,
1569     const struct GNUNET_CRYPTO_RsaSignature *signature)
1570 {
1571   struct ZoneToNameCtx *ztn_ctx = cls;
1572   struct ZoneToNameResponseMessage *ztnr_msg;
1573   int16_t res = GNUNET_SYSERR;
1574   uint16_t name_len = 0;
1575   uint16_t rd_ser_len = 0 ;
1576   int32_t contains_sig = 0;
1577   size_t msg_size = 0;
1578
1579   char *rd_ser = NULL;
1580   char *name_tmp;
1581   char *rd_tmp;
1582   char *sig_tmp;
1583
1584   if ((zone_key != NULL) && (name != NULL))
1585   {
1586     /* found result */
1587     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1588     res = GNUNET_YES;
1589     name_len = strlen (name) +1;
1590   }
1591   else
1592   {
1593     /* no result found */
1594     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1595     res = GNUNET_NO;
1596     name_len = 0;
1597   }
1598
1599   if (rd_count > 0)
1600   {
1601     rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1602     rd_ser = GNUNET_malloc (rd_ser_len);
1603     GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1604   }
1605   else
1606     rd_ser_len = 0;
1607
1608   if (signature != NULL)
1609     contains_sig = GNUNET_YES;
1610   else
1611     contains_sig = GNUNET_NO;
1612
1613   msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1614   ztnr_msg = GNUNET_malloc (msg_size);
1615
1616   name_tmp = (char *) &ztnr_msg[1];
1617   rd_tmp = &name_tmp[name_len];
1618   sig_tmp = &rd_tmp[rd_ser_len];
1619
1620   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1621   ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1622   ztnr_msg->gns_header.header.size = htons (msg_size);
1623   ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1624   ztnr_msg->res = htons (res);
1625   ztnr_msg->rd_len = htons (rd_ser_len);
1626   ztnr_msg->rd_count = htons (rd_count);
1627   ztnr_msg->name_len = htons (name_len);
1628   ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1629   if (zone_key != NULL)
1630     ztnr_msg->zone_key = *zone_key;
1631   else
1632     memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1633
1634   if ((name_len > 0) && (name != NULL))
1635     memcpy (name_tmp, name, name_len);
1636
1637   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name is `%s', has %u records, rd ser len %u msg_size %u\n", name, rd_count, rd_ser_len, msg_size);
1638   if ((rd_ser_len > 0) && (rd_ser != NULL))
1639     memcpy (rd_tmp, rd_ser, rd_ser_len);
1640   if ((GNUNET_YES == contains_sig) && (signature != NULL))
1641     memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1642
1643   GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1644   GNUNET_free (ztnr_msg);
1645   GNUNET_free_non_null (rd_ser);
1646 }
1647
1648
1649 /**
1650  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1651  *
1652  * @param cls unused
1653  * @param client GNUNET_SERVER_Client sending the message
1654  * @param message message of type 'struct ZoneToNameMessage'
1655  */
1656 static void
1657 handle_zone_to_name (void *cls,
1658                      struct GNUNET_SERVER_Client *client,
1659                      const struct GNUNET_MessageHeader *message)
1660 {
1661   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1662   struct GNUNET_NAMESTORE_Client *nc;
1663   struct ZoneToNameMessage *ztn_msg;
1664   struct ZoneToNameCtx ztn_ctx;
1665   size_t msg_size = 0;
1666   uint32_t rid = 0;
1667
1668   if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1669   {
1670     GNUNET_break_op (0);
1671     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1672     return;
1673   }
1674
1675   nc = client_lookup(client);
1676   if (nc == NULL)
1677   {
1678     GNUNET_break_op (0);
1679     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1680     return;
1681   }
1682
1683   ztn_msg = (struct ZoneToNameMessage *) message;
1684
1685   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1686   {
1687     GNUNET_break_op (0);
1688     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1689     return;
1690   }
1691
1692   rid = ntohl (ztn_msg->gns_header.r_id);
1693
1694   ztn_ctx.rid = rid;
1695   ztn_ctx.nc = nc;
1696
1697   struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1698   GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1699   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1700       (char *) &z_tmp,
1701       GNUNET_short_h2s (&ztn_msg->value_zone));
1702
1703   GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1704
1705   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1706 }
1707
1708
1709 /**
1710  * Copy record, data has to be free'd separetely
1711  *
1712  * @param src source record
1713  * @param dest destination record
1714  */
1715 static void
1716 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1717 {
1718   memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1719   dest->data = GNUNET_malloc (src->data_size);
1720   memcpy ((void *) dest->data, src->data, src->data_size);
1721 }
1722
1723
1724 /**
1725  * ZoneIterationProcResult
1726  *
1727  * Context for record remove operations passed from
1728  * 'find_next_zone_iteration_result' to 'zone_iteraterate_proc' as closure
1729  */
1730 struct ZoneIterationProcResult
1731 {
1732   /**
1733    * The zone iteration handle
1734    */
1735   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1736
1737   /**
1738    * Iteration result: iteration done?
1739    */
1740   int res_iteration_finished;
1741
1742   /**
1743    * Iteration result: number of records included
1744    */
1745   int records_included;
1746
1747   /**
1748    * Iteration result: is a valid signature included?
1749    */
1750   int has_signature;
1751
1752   /**
1753    * Name
1754    */
1755   char *name;
1756
1757   /**
1758    * Zone hash
1759    */
1760   struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1761
1762   /**
1763    * Record data
1764    */
1765   struct GNUNET_NAMESTORE_RecordData *rd;
1766
1767   /**
1768    * Zone's public key
1769    */
1770   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1771
1772   /**
1773    * Signature
1774    */
1775   struct GNUNET_CRYPTO_RsaSignature signature;
1776
1777   /**
1778    * Expiration date
1779    */
1780   struct GNUNET_TIME_Absolute expire;
1781 };
1782
1783
1784 /**
1785  * Process results for zone iteration from database
1786  *
1787  * @param cls struct ZoneIterationProcResult *proc
1788  * @param zone_key the zone key
1789  * @param expire expiration time
1790  * @param name name
1791  * @param rd_count number of records for this name
1792  * @param rd record data
1793  * @param signature block signature
1794  */
1795 static void
1796 zone_iteraterate_proc (void *cls,
1797                        const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1798                        struct GNUNET_TIME_Absolute expire,
1799                        const char *name,
1800                        unsigned int rd_count,
1801                        const struct GNUNET_NAMESTORE_RecordData *rd,
1802                        const struct GNUNET_CRYPTO_RsaSignature *signature)
1803 {
1804   struct ZoneIterationProcResult *proc = cls;
1805   struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1806   struct GNUNET_CRYPTO_RsaSignature *new_signature;
1807   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1808   struct GNUNET_CRYPTO_ShortHashCode hash;
1809   struct GNUNET_HashCode long_hash;
1810   struct GNUNET_TIME_Absolute e;
1811   unsigned int rd_count_filtered  = 0;
1812   int include;
1813   int c;
1814
1815   proc->res_iteration_finished = GNUNET_NO;
1816   proc->records_included = 0;
1817
1818   if ((zone_key == NULL) && (name == NULL))
1819   {
1820     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1821     proc->res_iteration_finished = GNUNET_YES;
1822     proc->rd = NULL;
1823     proc->name = NULL;
1824   }
1825   else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1826   {
1827     rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1828     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1829     for (c = 0; c < rd_count; c++)
1830     {
1831       include = GNUNET_YES;
1832       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1833           c, rd[c].flags, proc->zi->must_have_flags);
1834       /* Checking must have flags */
1835       if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1836       {
1837         /* Include */
1838         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1839       }
1840       else
1841       {
1842         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1843         include = GNUNET_NO;
1844       }
1845
1846       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1847           c, rd[c].flags, proc->zi->must_not_have_flags);
1848       if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1849       {
1850         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1851         include = GNUNET_NO;
1852       }
1853       else
1854       {
1855         /* Include */
1856         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1857       }
1858       if (GNUNET_YES == include)
1859       {
1860         copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1861         rd_count_filtered++;
1862       }
1863
1864     }
1865     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1866
1867     proc->records_included = rd_count_filtered;
1868     if (0 == rd_count_filtered)
1869     {
1870       GNUNET_free (rd_filtered);
1871       rd_filtered = NULL;
1872     }
1873     proc->rd = rd_filtered;
1874     proc->name = GNUNET_strdup(name);
1875     memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1876
1877     /* Signature */
1878     proc->has_signature = GNUNET_NO;
1879     GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1880     GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1881     proc->zone_hash = hash;
1882
1883     if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1884     {
1885       cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1886       e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1887       proc->expire = e;
1888       new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1889       GNUNET_assert (signature != NULL);
1890       proc->signature = (*new_signature);
1891       GNUNET_free (new_signature);
1892       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1893           name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1894       proc->has_signature = GNUNET_YES;
1895     }
1896     else if (rd_count_filtered == rd_count)
1897     {
1898       proc->expire = expire;
1899       if (NULL != signature)
1900       {
1901         proc->signature = (*signature);
1902         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1903             name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1904         proc->has_signature = GNUNET_YES;
1905       }
1906       else
1907       {
1908         memset (&proc->signature, '\0', sizeof (proc->signature));
1909         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1910       }
1911     }
1912   }
1913   else
1914   {
1915     GNUNET_break (0);
1916     return;
1917   }
1918 }
1919 /////////////////////////////////////////////////////////////
1920
1921
1922 /**
1923  * Find next zone iteration result in database
1924  *
1925  * @param proc the zone iteration processing to use
1926  */
1927 static void
1928 find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1929 {
1930   struct GNUNET_CRYPTO_ShortHashCode *zone;
1931
1932   if (GNUNET_YES == proc->zi->has_zone)
1933     zone = &proc->zi->zone;
1934   else
1935     zone = NULL;
1936   do
1937   {
1938     if (GNUNET_SYSERR ==
1939         GSN_database->iterate_records (GSN_database->cls, zone, NULL, 
1940                                        proc->zi->offset, 
1941                                        &zone_iteraterate_proc, proc))
1942     {
1943       GNUNET_break (0);
1944       break;
1945     }
1946     proc->zi->offset++;
1947   }
1948   while ((0 == proc->records_included) && (GNUNET_NO == proc->res_iteration_finished));
1949 }
1950
1951
1952 /**
1953  * Send zone iteration result to client
1954  *
1955  * @param proc the zone iteration processing result to send
1956  */
1957 static void
1958 send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1959 {
1960   struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1961   struct ZoneIterationResponseMessage zir_end;
1962   struct ZoneIterationResponseMessage *zir_msg;
1963   size_t name_len;
1964   size_t rd_ser_len;
1965   size_t msg_size;
1966   char *name_tmp;
1967   char *rd_ser;
1968
1969   if (GNUNET_YES == proc->res_iteration_finished)
1970   {
1971     if (zi->has_zone == GNUNET_YES)
1972       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1973                   "No more results for zone `%s'\n", 
1974                   GNUNET_short_h2s(&zi->zone));
1975     else
1976       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1977                   "No more results for all zones\n");
1978     memset (&zir_end, 0, sizeof (zir_end));
1979     zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1980     zir_end.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1981     zir_end.gns_header.r_id = htonl(zi->request_id);
1982     GNUNET_SERVER_notification_context_unicast (snc, 
1983                                                 zi->client->client, 
1984                                                 &zir_end.gns_header.header, GNUNET_NO);
1985     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1986     GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1987     GNUNET_free (zi);
1988     return;
1989   }
1990   GNUNET_assert (proc->records_included > 0);
1991   if (GNUNET_YES == zi->has_zone)
1992     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1993                 "Sending name `%s' for iteration over zone `%s'\n",
1994                 proc->name, GNUNET_short_h2s(&zi->zone));
1995   else
1996     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1997                 "Sending name `%s' for iteration over all zones\n",
1998                 proc->name);
1999   name_len = strlen (proc->name) + 1;
2000   rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);  
2001   msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
2002
2003   zir_msg = GNUNET_malloc(msg_size);
2004   zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
2005   zir_msg->gns_header.header.size = htons (msg_size);
2006   zir_msg->gns_header.r_id = htonl(zi->request_id);
2007   zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire);
2008   zir_msg->reserved = htons (0);
2009   zir_msg->name_len = htons (name_len);
2010   zir_msg->rd_count = htons (proc->records_included);
2011   zir_msg->rd_len = htons (rd_ser_len);
2012   zir_msg->signature = proc->signature;
2013   zir_msg->public_key = proc->zone_key;
2014   name_tmp = (char *) &zir_msg[1];
2015   memcpy (name_tmp, proc->name, name_len);
2016   rd_ser = &name_tmp[name_len];
2017   GNUNET_NAMESTORE_records_serialize (proc->records_included, proc->rd, rd_ser_len, rd_ser);
2018   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2019               "Sending `%s' message with size %u\n", 
2020               "ZONE_ITERATION_RESPONSE",
2021               msg_size);
2022   GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, 
2023                                               (const struct GNUNET_MessageHeader *) zir_msg,
2024                                               GNUNET_NO);
2025   GNUNET_free (zir_msg);
2026 }
2027
2028
2029 /**
2030  * Clean up after zone iteration
2031  * @param proc the zone iteration processor
2032  */
2033 static void
2034 clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
2035 {
2036   unsigned int c;
2037
2038   GNUNET_free_non_null (proc->name);
2039   proc->name = NULL;
2040   for (c = 0; c < proc->records_included; c++)  
2041     GNUNET_free ((void *) proc->rd[c].data);  
2042   GNUNET_free_non_null (proc->rd);
2043   proc->rd = NULL;
2044   proc->records_included = 0;
2045 }
2046
2047
2048 /**
2049  * Perform the next round of the zone iteration.
2050  *
2051  * @param zi zone iterator to process
2052  */
2053 static void
2054 run_zone_iteration_round (struct GNUNET_NAMESTORE_ZoneIteration *zi)
2055 {
2056   struct ZoneIterationProcResult proc;
2057
2058   memset (&proc, 0, sizeof (proc));
2059   proc.zi = zi;
2060   find_next_zone_iteration_result (&proc);
2061   if (GNUNET_YES == proc.res_iteration_finished)
2062   {
2063     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2064                 "Zone iteration done\n");
2065   }
2066   else if (0 != proc.records_included)
2067   {
2068     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2069                 "Zone iteration returns %u records\n", 
2070                 proc.records_included);
2071   }
2072   send_zone_iteration_result (&proc);
2073   clean_up_zone_iteration_result (&proc);
2074 }
2075
2076
2077 /**
2078  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
2079  *
2080  * @param cls unused
2081  * @param client GNUNET_SERVER_Client sending the message
2082  * @param message message of type 'struct ZoneIterationStartMessage'
2083  */
2084 static void
2085 handle_iteration_start (void *cls,
2086                         struct GNUNET_SERVER_Client *client,
2087                         const struct GNUNET_MessageHeader *message)
2088 {
2089   static struct GNUNET_CRYPTO_ShortHashCode zeros;
2090   const struct ZoneIterationStartMessage *zis_msg;
2091   struct GNUNET_NAMESTORE_Client *nc;
2092   struct GNUNET_NAMESTORE_ZoneIteration *zi;
2093
2094   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2095   nc = client_lookup (client);
2096   if (NULL == nc)
2097   {
2098     GNUNET_break_op (0);
2099     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2100     return;
2101   }
2102   zis_msg = (const struct ZoneIterationStartMessage *) message;
2103   zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2104   zi->request_id = ntohl (zis_msg->gns_header.r_id);
2105   zi->offset = 0;
2106   zi->client = nc;
2107   zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2108   zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2109   if (0 == memcmp (&zeros, &zis_msg->zone, sizeof (zeros)))
2110   {
2111     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2112     zi->zone = zis_msg->zone;
2113     zi->has_zone = GNUNET_NO;
2114   }
2115   else
2116   {
2117     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2118                 "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2119     zi->zone = zis_msg->zone;
2120     zi->has_zone = GNUNET_YES;
2121   }
2122   GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2123   run_zone_iteration_round (zi);
2124   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2125 }
2126
2127
2128 /**
2129  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2130  *
2131  * @param cls unused
2132  * @param client GNUNET_SERVER_Client sending the message
2133  * @param message message of type 'struct ZoneIterationStopMessage'
2134  */
2135 static void
2136 handle_iteration_stop (void *cls,
2137                        struct GNUNET_SERVER_Client *client,
2138                        const struct GNUNET_MessageHeader *message)
2139 {
2140   struct GNUNET_NAMESTORE_Client *nc;
2141   struct GNUNET_NAMESTORE_ZoneIteration *zi;
2142   const struct ZoneIterationStopMessage *zis_msg;
2143   uint32_t rid;
2144
2145   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2146               "Received `%s' message\n",
2147               "ZONE_ITERATION_STOP");
2148   nc = client_lookup(client);
2149   if (NULL == nc)
2150   {
2151     GNUNET_break (0);
2152     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2153     return;
2154   }
2155   zis_msg = (const struct ZoneIterationStopMessage *) message;
2156   rid = ntohl (zis_msg->gns_header.r_id);
2157   for (zi = nc->op_head; NULL != zi; zi = zi->next)
2158     if (zi->request_id == rid)
2159       break;
2160   if (NULL == zi)
2161   {
2162     GNUNET_break (0);
2163     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2164     return;
2165   }
2166   GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2167   if (GNUNET_YES == zi->has_zone)
2168     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2169                 "Stopped zone iteration for zone `%s'\n",
2170                 GNUNET_short_h2s (&zi->zone));
2171   else
2172     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2173                 "Stopped zone iteration over all zones\n");
2174   GNUNET_free (zi);
2175   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2176 }
2177
2178
2179 /**
2180  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT' message
2181  *
2182  * @param cls unused
2183  * @param client GNUNET_SERVER_Client sending the message
2184  * @param message message of type 'struct ZoneIterationNextMessage'
2185  */
2186 static void
2187 handle_iteration_next (void *cls,
2188                        struct GNUNET_SERVER_Client *client,
2189                        const struct GNUNET_MessageHeader *message)
2190 {
2191   struct GNUNET_NAMESTORE_Client *nc;
2192   struct GNUNET_NAMESTORE_ZoneIteration *zi;
2193   const struct ZoneIterationNextMessage *zis_msg;
2194   uint32_t rid;
2195
2196   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2197   nc = client_lookup(client);
2198   if (NULL == nc)
2199   {
2200     GNUNET_break (0);
2201     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2202     return;
2203   }
2204   zis_msg = (const struct ZoneIterationNextMessage *) message;
2205   rid = ntohl (zis_msg->gns_header.r_id);
2206   for (zi = nc->op_head; NULL != zi; zi = zi->next)
2207     if (zi->request_id == rid)
2208       break;
2209   if (NULL == zi)
2210   {
2211     GNUNET_break (0);
2212     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2213     return;
2214   }
2215   run_zone_iteration_round (zi);
2216   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2217 }
2218
2219
2220 /**
2221  * Load zone keys from directory by reading all .zkey files in this directory
2222  *
2223  * @param cls int * 'counter' to store the number of files found
2224  * @param filename directory to scan
2225  * @return GNUNET_OK to continue
2226  */
2227 static int
2228 zonekey_file_it (void *cls, const char *filename)
2229 {
2230   unsigned int *counter = cls;
2231   struct GNUNET_HashCode long_hash;
2232   struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2233   struct GNUNET_NAMESTORE_CryptoContainer *c;
2234
2235   if ((NULL == filename) ||
2236       (NULL == strstr(filename, ".zkey")))
2237     return GNUNET_OK;
2238   privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
2239   if (NULL == privkey)
2240   {
2241     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2242                 _("Could not parse zone key file `%s'\n"),
2243                 filename);
2244     return GNUNET_OK;
2245   }
2246   c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
2247   c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2248   c->privkey = privkey;
2249   GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
2250   GNUNET_CRYPTO_short_hash(c->pubkey, 
2251                            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), 
2252                            &c->zone);
2253   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2254               "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
2255   GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
2256   GNUNET_assert (GNUNET_OK == 
2257                  GNUNET_CONTAINER_multihashmap_put (zonekeys, &long_hash, c, 
2258                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2259   (*counter)++;
2260   return GNUNET_OK;
2261 }
2262
2263
2264 /**
2265  * Process namestore requests.
2266  *
2267  * @param cls closure
2268  * @param server the initialized server
2269  * @param cfg configuration to use
2270  */
2271 static void
2272 run (void *cls, struct GNUNET_SERVER_Handle *server,
2273      const struct GNUNET_CONFIGURATION_Handle *cfg)
2274 {
2275   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2276     {&handle_start, NULL,
2277      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2278     {&handle_lookup_name, NULL,
2279      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2280     {&handle_record_put, NULL,
2281     GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2282     {&handle_record_create, NULL,
2283      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2284     {&handle_record_remove, NULL,
2285      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2286     {&handle_zone_to_name, NULL,
2287       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
2288     {&handle_iteration_start, NULL,
2289      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage) },
2290     {&handle_iteration_next, NULL,
2291      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, sizeof (struct ZoneIterationNextMessage) },
2292      {&handle_iteration_stop, NULL,
2293       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage) },
2294     {NULL, NULL, 0, 0}
2295   };
2296   char *database;
2297   unsigned int counter;
2298
2299   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2300   GSN_cfg = cfg;
2301
2302   /* Load private keys from disk */
2303   if (GNUNET_OK !=
2304       GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", 
2305                                                "zonefile_directory",
2306                                                &zonefile_directory))
2307   {
2308     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
2309                 _("No directory to load zonefiles specified in configuration\n"));
2310     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2311     return;
2312   }
2313
2314   if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2315   {
2316     if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2317     {
2318       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
2319                   _("Creating directory `%s' for zone files failed!\n"),
2320                   zonefile_directory);
2321       GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2322       return;
2323     }
2324     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2325                 "Created directory `%s' for zone files\n", 
2326                 zonefile_directory);
2327   }
2328
2329   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2330               "Scanning directory `%s' for zone files\n", zonefile_directory);
2331   zonekeys = GNUNET_CONTAINER_multihashmap_create (16);
2332   counter = 0;
2333   GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2334   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
2335               "Found %u zone files\n", 
2336               counter);
2337
2338   /* Loading database plugin */
2339   if (GNUNET_OK !=
2340       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2341                                              &database))
2342     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2343
2344   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2345   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2346   GNUNET_free (database);
2347   if (NULL == GSN_database)
2348   {
2349     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
2350                 "Could not load database backend `%s'\n",
2351                 db_lib_name);
2352     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2353     return;
2354   }
2355
2356   /* Configuring server handles */
2357   GNUNET_SERVER_add_handlers (server, handlers);
2358   snc = GNUNET_SERVER_notification_context_create (server, 16);
2359   GNUNET_SERVER_disconnect_notify (server,
2360                                    &client_disconnect_notification,
2361                                    NULL);
2362   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2363                                 NULL);
2364 }
2365
2366
2367 /**
2368  * The main function for the template service.
2369  *
2370  * @param argc number of arguments from the command line
2371  * @param argv command line arguments
2372  * @return 0 ok, 1 on error
2373  */
2374 int
2375 main (int argc, char *const *argv)
2376 {
2377   return (GNUNET_OK ==
2378           GNUNET_SERVICE_run (argc, argv, "namestore",
2379                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2380 }
2381
2382 /* end of gnunet-service-namestore.c */
2383