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