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