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