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