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