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