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