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