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