- fix
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file namestore/gnunet-service-namestore.c
23  * @brief namestore for the GNUnet naming system
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "gnunet_signatures.h"
32 #include "namestore.h"
33
34 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
35
36 /**
37  * A namestore operation.
38  */
39 struct GNUNET_NAMESTORE_ZoneIteration
40 {
41   struct GNUNET_NAMESTORE_ZoneIteration *next;
42   struct GNUNET_NAMESTORE_ZoneIteration *prev;
43
44   struct GNUNET_NAMESTORE_Client * client;
45
46   int has_zone;
47
48   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;
428   else
429     contains_signature = GNUNET_NO;
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   //size_t len;
1336
1337   if ((zone_key == NULL) && (name == NULL))
1338   {
1339     struct ZoneIterationResponseMessage zir_msg;
1340     if (zi->has_zone == GNUNET_YES)
1341       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_h2s(&zi->zone));
1342     else
1343       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n");
1344
1345     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE");
1346     zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1347     zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1348     zir_msg.gns_header.r_id = htonl(zi->request_id);
1349     zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_absolute_get_zero());
1350     zir_msg.name_len = htons (0);
1351     zir_msg.reserved = htons (0);
1352     zir_msg.rd_count = htons (0);
1353     zir_msg.rd_len = htons (0);
1354     memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key));
1355     memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature));
1356     GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1357
1358     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1359     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
1360     GNUNET_free (zi);
1361     return;
1362   }
1363   else
1364   {
1365     struct ZoneIterationResponseMessage *zir_msg;
1366     if (zi->has_zone == GNUNET_YES)
1367       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n",
1368           name, GNUNET_h2s(&zi->zone));
1369     if (zi->has_zone == GNUNET_NO)
1370       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n",
1371           name);
1372
1373     size_t name_len;
1374     size_t rd_ser_len;
1375     size_t msg_size;
1376     char *name_tmp;
1377     char *rd_tmp;
1378     name_len = strlen (name) +1;
1379
1380     rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1381     char rd_ser[rd_ser_len];
1382     GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1383     msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1384     zir_msg = GNUNET_malloc(msg_size);
1385
1386     name_tmp = (char *) &zir_msg[1];
1387     rd_tmp = &name_tmp[name_len];
1388
1389     zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1390     zir_msg->gns_header.header.size = htons (msg_size);
1391     zir_msg->gns_header.r_id = htonl(zi->request_id);
1392     zir_msg->expire = GNUNET_TIME_absolute_hton(expire);
1393     zir_msg->reserved = htons (0);
1394     zir_msg->name_len = htons (name_len);
1395     zir_msg->rd_count = htons (rd_count);
1396     zir_msg->rd_len = htons (rd_ser_len);
1397     zir_msg->signature = *signature;
1398     GNUNET_assert (NULL != zone_key);
1399     if (zone_key != NULL)
1400       zir_msg->public_key = *zone_key;
1401     memcpy (name_tmp, name, name_len);
1402     memcpy (rd_tmp, rd_ser, rd_ser_len);
1403
1404     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size);
1405     GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) zir_msg, GNUNET_NO);
1406     GNUNET_free (zir_msg);
1407   }
1408 }
1409
1410 static void handle_iteration_start (void *cls,
1411                           struct GNUNET_SERVER_Client * client,
1412                           const struct GNUNET_MessageHeader * message)
1413 {
1414   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
1415
1416   struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message;
1417   struct GNUNET_NAMESTORE_Client *nc;
1418   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1419   int res;
1420
1421   nc = client_lookup(client);
1422   if (nc == NULL)
1423   {
1424     GNUNET_break_op (0);
1425     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1426     return;
1427   }
1428
1429   zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
1430   zi->request_id = ntohl (zis_msg->gns_header.r_id);
1431   zi->offset = 0;
1432   zi->client = nc;
1433   zi->zone = zis_msg->zone;
1434
1435   GNUNET_HashCode dummy;
1436   GNUNET_HashCode *zone_tmp;
1437   memset (&dummy, '\0', sizeof (dummy));
1438   if (0 == memcmp (&dummy, &zis_msg->zone, sizeof (dummy)))
1439   {
1440     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
1441     zi->has_zone = GNUNET_NO;
1442     zone_tmp = NULL;
1443   }
1444   else
1445   {
1446     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over zone  `%s'\n", GNUNET_h2s (&zis_msg->zone));
1447     zi->has_zone = GNUNET_YES;
1448     zone_tmp = &zis_msg->zone;
1449   }
1450
1451   GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1452
1453   res = GSN_database->iterate_records (GSN_database->cls, zone_tmp , NULL, zi->offset , &zone_iteration_proc, zi);
1454   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1455 }
1456
1457 static void handle_iteration_stop (void *cls,
1458                           struct GNUNET_SERVER_Client * client,
1459                           const struct GNUNET_MessageHeader * message)
1460 {
1461   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1462
1463   struct GNUNET_NAMESTORE_Client *nc;
1464   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1465   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1466   uint32_t rid;
1467
1468   nc = client_lookup(client);
1469   if (nc == NULL)
1470   {
1471     GNUNET_break_op (0);
1472     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1473     return;
1474   }
1475
1476   rid = ntohl (zis_msg->gns_header.r_id);
1477   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1478   {
1479     if (zi->request_id == rid)
1480       break;
1481   }
1482   if (zi == NULL)
1483   {
1484     GNUNET_break_op (0);
1485     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1486     return;
1487   }
1488
1489   GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1490   if (GNUNET_YES == zi->has_zone)
1491     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone));
1492   else
1493     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration all zones\n");
1494   GNUNET_free (zi);
1495
1496   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1497 }
1498
1499 static void handle_iteration_next (void *cls,
1500                           struct GNUNET_SERVER_Client * client,
1501                           const struct GNUNET_MessageHeader * message)
1502 {
1503   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1504
1505   struct GNUNET_NAMESTORE_Client *nc;
1506   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1507   GNUNET_HashCode *zone_tmp;
1508   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1509   uint32_t rid;
1510
1511   nc = client_lookup(client);
1512   if (nc == NULL)
1513   {
1514     GNUNET_break_op (0);
1515     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1516     return;
1517   }
1518
1519   rid = ntohl (zis_msg->gns_header.r_id);
1520   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1521   {
1522     if (zi->request_id == rid)
1523       break;
1524   }
1525   if (zi == NULL)
1526   {
1527     GNUNET_break_op (0);
1528     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1529     return;
1530   }
1531
1532   if (GNUNET_YES == zi->has_zone)
1533     zone_tmp = &zi->zone;
1534   else
1535     zone_tmp = NULL;
1536
1537   zi->offset++;
1538   GSN_database->iterate_records (GSN_database->cls, zone_tmp, NULL, zi->offset , &zone_iteration_proc, zi);
1539   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1540 }
1541
1542 int zonekey_file_it (void *cls, const char *filename)
1543 {
1544   int *counter = cls;
1545    if ((filename != NULL) && (NULL != strstr(filename, ".zone")))
1546    {
1547      struct GNUNET_CRYPTO_RsaPrivateKey * privkey;
1548      struct GNUNET_NAMESTORE_CryptoContainer *c;
1549      privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
1550      if (privkey == NULL)
1551        return GNUNET_OK;
1552
1553      c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1554      c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1555      c->privkey = privkey;
1556      GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
1557      GNUNET_CRYPTO_hash(c->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &c->zone);
1558
1559      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found zonefile for zone `%s'\n", GNUNET_h2s (&c->zone));
1560
1561      GNUNET_CONTAINER_multihashmap_put(zonekeys, &c->zone, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1562      (*counter) ++;
1563    }
1564    return GNUNET_OK;
1565 }
1566
1567
1568 /**
1569  * Process template requests.
1570  *
1571  * @param cls closure
1572  * @param server the initialized server
1573  * @param cfg configuration to use
1574  */
1575 static void
1576 run (void *cls, struct GNUNET_SERVER_Handle *server,
1577      const struct GNUNET_CONFIGURATION_Handle *cfg)
1578 {
1579   char * database;
1580   int counter = 0;
1581   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1582
1583   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1584     {&handle_start, NULL,
1585      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
1586     {&handle_lookup_name, NULL,
1587      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
1588     {&handle_record_put, NULL,
1589     GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
1590     {&handle_record_create, NULL,
1591      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
1592     {&handle_record_remove, NULL,
1593      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
1594     {&handle_zone_to_name, NULL,
1595       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
1596     {&handle_iteration_start, NULL,
1597      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
1598     {&handle_iteration_next, NULL,
1599      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
1600      {&handle_iteration_stop, NULL,
1601       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0},
1602     {NULL, NULL, 0, 0}
1603   };
1604
1605   GSN_cfg = cfg;
1606
1607   /* Load private keys from disk */
1608   if (GNUNET_OK !=
1609       GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", "zonefile_directory",
1610                                              &zonefile_directory))
1611   {
1612     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No directory to load zonefiles specified in configuration\n"));
1613     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1614     return;
1615   }
1616
1617   if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
1618   {
1619     if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
1620     {
1621       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Creating directory `%s' for zone files failed!\n"), zonefile_directory);
1622       GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1623       return;
1624     }
1625     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created directory `%s' for zone files\n", zonefile_directory);
1626   }
1627
1628   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scanning directory `%s' for zone files\n", zonefile_directory);
1629   zonekeys = GNUNET_CONTAINER_multihashmap_create (10);
1630   GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
1631   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u zone files\n", counter);
1632
1633   /* Loading database plugin */
1634   if (GNUNET_OK !=
1635       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
1636                                              &database))
1637     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1638
1639   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1640   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1641   GNUNET_free (database);
1642   if (GSN_database == NULL)
1643   {
1644     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
1645         db_lib_name);
1646     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1647     return;
1648   }
1649
1650   /* Configuring server handles */
1651   GNUNET_SERVER_add_handlers (server, handlers);
1652   snc = GNUNET_SERVER_notification_context_create (server, 16);
1653   GNUNET_SERVER_disconnect_notify (server,
1654                                    &client_disconnect_notification,
1655                                    NULL);
1656
1657   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1658                                 NULL);
1659
1660 }
1661
1662
1663 /**
1664  * The main function for the template service.
1665  *
1666  * @param argc number of arguments from the command line
1667  * @param argv command line arguments
1668  * @return 0 ok, 1 on error
1669  */
1670 int
1671 main (int argc, char *const *argv)
1672 {
1673   return (GNUNET_OK ==
1674           GNUNET_SERVICE_run (argc, argv, "namestore",
1675                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1676 }
1677
1678 /* end of gnunet-service-namestore.c */
1679