- docu
[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 static 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 /**
413  * Called whenever a client is disconnected.
414  * Frees our resources associated with that client.
415  *
416  * @param cls closure
417  * @param client identification of the client
418  */
419 static void
420 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
421 {
422   struct GNUNET_NAMESTORE_ZoneIteration *no;
423   struct GNUNET_NAMESTORE_Client *nc;
424   if (NULL == client)
425     return;
426
427   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
428
429   nc = client_lookup (client);
430
431   if ((NULL == client) || (NULL == nc))
432     return;
433
434   no = nc->op_head;
435   while (NULL != no)
436   {
437     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
438     GNUNET_free (no);
439     no = nc->op_head;
440   }
441
442   GNUNET_SERVER_client_drop(nc->client);
443   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
444   GNUNET_free (nc);
445   nc = NULL;
446 }
447
448
449 /**
450  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
451  *
452  * @param cls unused
453  * @param client GNUNET_SERVER_Client sending the message
454  * @param message unused
455  */
456 static void
457 handle_start (void *cls,
458               struct GNUNET_SERVER_Client *client,
459               const struct GNUNET_MessageHeader *message)
460 {
461   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
462
463   struct GNUNET_NAMESTORE_Client *nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
464   nc->client = client;
465   GNUNET_SERVER_notification_context_add (snc, client);
466   GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
467   GNUNET_SERVER_client_keep (client);
468   GNUNET_SERVER_receive_done (client, GNUNET_OK);
469 }
470
471
472 /**
473  * LookupNameContext
474  *
475  * Context for name lookups passed from 'handle_lookup_name' to
476  * 'handle_lookup_name_it' as closure
477  */
478 struct LookupNameContext
479 {
480   /**
481    * The client to send the response to
482    */
483   struct GNUNET_NAMESTORE_Client *nc;
484
485   /**
486    * Operation id for the name lookup
487    */
488   uint32_t request_id;
489
490   /**
491    * Requested specific record type
492    */
493   uint32_t record_type;
494
495   /**
496    * Requested zone
497    */
498   struct GNUNET_CRYPTO_ShortHashCode *zone;
499
500   /**
501    * Requested name
502    */
503   char *name;
504 };
505
506
507 /**
508  * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
509  *
510  * @param cls a 'struct LookupNameContext *' with information about the request
511  * @param zone_key zone key of the zone
512  * @param expire expiration time
513  * @param name name
514  * @param rd_count number of records
515  * @param rd array of records
516  * @param signature signature
517  */
518 static void
519 handle_lookup_name_it (void *cls,
520     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
521     struct GNUNET_TIME_Absolute expire,
522     const char *name,
523     unsigned int rd_count,
524     const struct GNUNET_NAMESTORE_RecordData *rd,
525     const struct GNUNET_CRYPTO_RsaSignature *signature)
526 {
527   /* send response */
528   struct LookupNameContext *lnc = cls;
529   struct LookupNameResponseMessage *lnr_msg;
530   struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
531   struct GNUNET_NAMESTORE_CryptoContainer *cc;
532   struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
533   struct GNUNET_TIME_Absolute e;
534   struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
535   struct GNUNET_HashCode long_hash;
536   char *rd_tmp;
537   char *name_tmp;
538   size_t rd_ser_len;
539   size_t r_size = 0;
540   size_t name_len = 0;
541
542   int copied_elements = 0;
543   int contains_signature = GNUNET_NO;
544   int authoritative = GNUNET_NO;
545   int c;
546
547   if (NULL != name)
548     name_len = strlen(name) + 1;
549
550   /* count records to copy */
551   if (rd_count != 0)
552   {
553     if (lnc->record_type != 0)
554     {
555       /* special record type needed */
556       for (c = 0; c < rd_count; c ++)
557         if (rd[c].record_type == lnc->record_type)
558           copied_elements++; /* found matching record */
559       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
560           copied_elements, lnc->record_type, lnc->name, GNUNET_short_h2s(lnc->zone));
561       rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
562       copied_elements = 0;
563       for (c = 0; c < rd_count; c ++)
564       {
565         if (rd[c].record_type == lnc->record_type)
566         {
567           /* found matching record */
568           memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
569           copied_elements++;
570         }
571       }
572     }
573     else
574     {
575       copied_elements = rd_count;
576       rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
577     }
578   }
579   else
580   {
581     /* No results */
582     copied_elements = 0;
583     rd_selected = NULL;
584     expire = GNUNET_TIME_UNIT_ZERO_ABS;
585   }
586
587   rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
588   char rd_ser[rd_ser_len];
589   GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
590
591   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
592       copied_elements, lnc->name, GNUNET_short_h2s(lnc->zone));
593
594   if ((copied_elements == rd_count) && (NULL != signature))
595     contains_signature = GNUNET_YES; /* returning all records, so include signature */
596   else
597     contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
598
599
600   if ((NULL != zone_key) && (copied_elements == rd_count))
601   {
602     GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash);
603     GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
604     if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
605     {
606       cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
607       e = get_block_expiration_time(rd_count, rd);
608       signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count);
609       GNUNET_assert (signature_new != NULL);
610       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));
611       authoritative = GNUNET_YES;
612     }
613     else
614       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am not authoritative for name `%s' in zone `%s'\n",name, GNUNET_short_h2s(&zone_key_hash));
615   }
616
617   r_size = sizeof (struct LookupNameResponseMessage) +
618            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
619            name_len +
620            rd_ser_len;
621
622   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
623   lnr_msg = GNUNET_malloc (r_size);
624   lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
625   lnr_msg->gns_header.header.size = ntohs (r_size);
626   lnr_msg->gns_header.r_id = htonl (lnc->request_id);
627   lnr_msg->rd_count = htons (copied_elements);
628   lnr_msg->rd_len = htons (rd_ser_len);
629   lnr_msg->name_len = htons (name_len);
630   lnr_msg->expire = GNUNET_TIME_absolute_hton(get_block_expiration_time(copied_elements, rd_selected));
631
632   if (rd_selected != rd)
633     GNUNET_free (rd_selected);
634
635   if (zone_key != NULL)
636     lnr_msg->public_key = (*zone_key);
637   else
638     memset(&lnr_msg->public_key, '\0', sizeof (lnr_msg->public_key));
639
640   if (GNUNET_YES == authoritative)
641   { /* use new created signature */
642     lnr_msg->contains_sig = htons (GNUNET_YES);
643     GNUNET_assert (signature_new != NULL);
644     lnr_msg->signature = *signature_new;
645     GNUNET_free (signature_new);
646   }
647   else if (GNUNET_YES == contains_signature)
648   {
649     /* use existing signature */
650     lnr_msg->contains_sig = htons (GNUNET_YES);
651     GNUNET_assert (signature != NULL);
652     lnr_msg->signature = *signature;
653   }
654   else
655   {
656     /* use no signature */
657     memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature));
658   }
659
660   name_tmp = (char *) &lnr_msg[1];
661   rd_tmp = &name_tmp[name_len];
662
663   memcpy (name_tmp, name, name_len);
664   memcpy (rd_tmp, rd_ser, rd_ser_len);
665
666   GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
667   GNUNET_free (lnr_msg);
668 }
669
670 /**
671  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
672  *
673  * @param cls unused
674  * @param client GNUNET_SERVER_Client sending the message
675  * @param message message of type 'struct LookupNameMessage'
676  */
677 static void
678 handle_lookup_name (void *cls,
679                     struct GNUNET_SERVER_Client *client,
680                     const struct GNUNET_MessageHeader *message)
681 {
682   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
683   struct LookupNameContext lnc;
684   struct GNUNET_NAMESTORE_Client *nc;
685   size_t name_len;
686   char *name;
687   uint32_t rid = 0;
688   uint32_t type = 0;
689
690   if (ntohs (message->size) < sizeof (struct LookupNameMessage))
691   {
692     GNUNET_break_op (0);
693     GNUNET_SERVER_receive_done (client, GNUNET_OK);
694     return;
695   }
696
697   nc = client_lookup(client);
698   if (nc == NULL)
699   {
700     GNUNET_break_op (0);
701     GNUNET_SERVER_receive_done (client, GNUNET_OK);
702     return;
703   }
704
705   struct LookupNameMessage *ln_msg = (struct LookupNameMessage *) message;
706   rid = ntohl (ln_msg->gns_header.r_id);
707   name_len = ntohl (ln_msg->name_len);
708   type = ntohl (ln_msg->record_type);
709
710   if ((name_len == 0) || (name_len > 256))
711   {
712     GNUNET_break_op (0);
713     GNUNET_SERVER_receive_done (client, GNUNET_OK);
714     return;
715   }
716
717   name = (char *) &ln_msg[1];
718   if (name[name_len -1] != '\0')
719   {
720     GNUNET_break_op (0);
721     GNUNET_SERVER_receive_done (client, GNUNET_OK);
722     return;
723   }
724
725   if (0 == type)
726     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_short_h2s(&ln_msg->zone));
727   else
728     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));
729
730   /* do the actual lookup */
731   lnc.request_id = rid;
732   lnc.nc = nc;
733   lnc.record_type = type;
734   lnc.name = name;
735   lnc.zone = &ln_msg->zone;
736   GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
737
738   GNUNET_SERVER_receive_done (client, GNUNET_OK);
739 }
740
741
742 /**
743  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
744  *
745  * @param cls unused
746  * @param client GNUNET_SERVER_Client sending the message
747  * @param message message of type 'struct RecordPutMessage'
748  */
749 static void
750 handle_record_put (void *cls,
751                    struct GNUNET_SERVER_Client *client,
752                    const struct GNUNET_MessageHeader *message)
753 {
754   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
755   struct GNUNET_NAMESTORE_Client *nc;
756   struct RecordPutMessage *rp_msg;
757   struct GNUNET_TIME_Absolute expire;
758   struct GNUNET_CRYPTO_RsaSignature *signature;
759   struct RecordPutResponseMessage rpr_msg;
760   struct GNUNET_CRYPTO_ShortHashCode zone_hash;
761   size_t name_len;
762   size_t msg_size;
763   size_t msg_size_exp;
764   char *name;
765   char *rd_ser;
766   uint32_t rid = 0;
767   uint32_t rd_ser_len;
768   uint32_t rd_count;
769   int res = GNUNET_SYSERR;
770
771   if (ntohs (message->size) < sizeof (struct RecordPutMessage))
772   {
773     GNUNET_break_op (0);
774     GNUNET_SERVER_receive_done (client, GNUNET_OK);
775     return;
776   }
777
778   nc = client_lookup (client);
779   if (nc == NULL)
780   {
781     GNUNET_break_op (0);
782     GNUNET_SERVER_receive_done (client, GNUNET_OK);
783     return;
784   }
785
786   rp_msg = (struct RecordPutMessage *) message;
787   rid = ntohl (rp_msg->gns_header.r_id);
788   msg_size = ntohs (rp_msg->gns_header.header.size);
789   name_len = ntohs (rp_msg->name_len);
790   rd_count = ntohs (rp_msg->rd_count);
791   rd_ser_len = ntohs(rp_msg->rd_len);
792
793   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
794   {
795     GNUNET_break_op (0);
796     GNUNET_SERVER_receive_done (client, GNUNET_OK);
797     return;
798   }
799
800   if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
801   {
802     GNUNET_break_op (0);
803     GNUNET_SERVER_receive_done (client, GNUNET_OK);
804     return;
805   }
806
807   msg_size_exp = sizeof (struct RecordPutMessage) +  name_len  + rd_ser_len;
808   if (msg_size != msg_size_exp)
809   {
810     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
811     GNUNET_break_op (0);
812     GNUNET_SERVER_receive_done (client, GNUNET_OK);
813     return;
814   }
815   if ((name_len == 0) || (name_len > 256))
816   {
817     GNUNET_break_op (0);
818     GNUNET_SERVER_receive_done (client, GNUNET_OK);
819     return;
820   }
821
822   name = (char *) &rp_msg[1];
823
824   if (name[name_len -1] != '\0')
825   {
826     GNUNET_break_op (0);
827     GNUNET_SERVER_receive_done (client, GNUNET_OK);
828     return;
829   }
830
831   expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
832   signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
833
834   rd_ser = &name[name_len];
835   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
836   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
837   if (res != GNUNET_OK)
838   {
839     GNUNET_break_op (0);
840     goto send;
841   }
842
843   GNUNET_CRYPTO_short_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash);
844   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_short_h2s(&zone_hash));
845
846   /* Database operation */
847   res = GSN_database->put_records(GSN_database->cls,
848                                 &rp_msg->public_key,
849                                 expire,
850                                 name,
851                                 rd_count, rd,
852                                 signature);
853
854   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
855       name, (res == GNUNET_OK) ? "OK" : "FAIL");
856
857   /* Send response */
858 send:
859   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
860   rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
861   rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
862   rpr_msg.gns_header.r_id = htonl (rid);
863   rpr_msg.op_result = htonl (res);
864   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
865
866   GNUNET_SERVER_receive_done (client, GNUNET_OK);
867 }
868
869
870 /**
871  * CreateRecordContext
872  *
873  * Context for record create operations passed from 'handle_record_create' to
874  * 'handle_create_record_it' as closure
875  */
876 struct CreateRecordContext
877 {
878   /**
879    * Record data
880    */
881   struct GNUNET_NAMESTORE_RecordData *rd;
882
883   /**
884    * Zone's private key
885    */
886   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
887
888   /**
889    * Zone's public key
890    */
891   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
892
893   /**
894    * Record expiration time
895    */
896   struct GNUNET_TIME_Absolute expire;
897
898   /**
899    * Name for the record to create
900    */
901   char *name;
902
903   /**
904    * result returned from 'handle_create_record_it'
905    * GNUNET_SYSERR: failed to create the record
906    * GNUNET_NO: we updated an existing record or identical entry existed
907    * GNUNET_YES : we created a new record
908    */
909   int res;
910 };
911
912
913 /**
914  * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
915  * in handle_record_create
916  *
917  * @param cls a 'struct CreateRecordContext *' with information about the request
918  * @param pubkey zone key of the zone
919  * @param expire expiration time
920  * @param name name
921  * @param rd_count number of records
922  * @param rd array of records
923  * @param signature signature
924  */
925 static void
926 handle_create_record_it (void *cls,
927                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
928                          struct GNUNET_TIME_Absolute expire,
929                          const char *name,
930                          unsigned int rd_count,
931                          const struct GNUNET_NAMESTORE_RecordData *rd,
932                          const struct GNUNET_CRYPTO_RsaSignature *signature)
933 {
934   struct CreateRecordContext *crc = cls;
935   struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
936   struct GNUNET_CRYPTO_RsaSignature dummy_signature;
937   struct GNUNET_TIME_Absolute block_expiration;
938   int res;
939   int exist = GNUNET_SYSERR;
940   int update = GNUNET_NO;
941   int c;
942   int rd_count_new = 0;
943
944   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
945   for (c = 0; c < rd_count; c++)
946   {
947     if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) && 
948          (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
949     {
950       /* Update unique PKEY */
951       exist = c;
952       update = GNUNET_YES;
953       break;
954     }
955     if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) && 
956          (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
957     {
958       /* Update unique PSEU */
959       exist = c;
960       update = GNUNET_YES;
961       break;
962     }
963     if ((crc->rd->record_type == rd[c].record_type) &&
964         (crc->rd->data_size == rd[c].data_size) &&
965         (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
966     {
967       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
968                   "Found existing records for `%s' to update expiration date!\n",
969                   crc->name);
970       exist = c;
971       if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
972            ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) 
973             == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
974         update = GNUNET_YES;
975       break;
976     }
977   }
978
979   if (exist == GNUNET_SYSERR)
980   {
981     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
982                 "No existing record for name `%s'!\n", 
983                 crc->name);
984     rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
985     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
986     rd_count_new = rd_count + 1;
987     rd_new[rd_count] = *(crc->rd);
988   }
989   else if (update == GNUNET_NO)
990   {
991     /* Exact same record already exists */
992     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
993                 "Matching record for %s' exists, no change required!\n",
994                 crc->name);
995     res = GNUNET_NO;
996     goto end;
997   }
998   else 
999   {
1000     /* Update record */
1001     GNUNET_assert (GNUNET_YES == update);
1002     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1003                 "Updating existing records for `%s'!\n", 
1004                 crc->name);
1005     rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
1006     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1007     rd_count_new = rd_count;
1008     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1009                 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) 
1010                 ? "Updating absolute expiration from %llu to %llu!\n"
1011                 : "Updating relative expiration from %llu to %llu!\n", 
1012                 rd_new[exist].expiration_time, crc->rd->expiration_time);
1013     rd_new[exist] = *(crc->rd);
1014   }
1015
1016   block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
1017   if (block_expiration.abs_value != expire.abs_value)
1018     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1019                 "Updated block expiration time\n");
1020
1021   memset (&dummy_signature, '\0', sizeof (dummy_signature));
1022
1023   /* Database operation */
1024   GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
1025   res = GSN_database->put_records(GSN_database->cls,
1026                                 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
1027                                 block_expiration,
1028                                 crc->name,
1029                                 rd_count_new, rd_new,
1030                                 &dummy_signature);
1031   GNUNET_break (GNUNET_OK == res);
1032   if (res == GNUNET_OK)
1033     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
1034   else
1035     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
1036   res = GNUNET_YES;
1037
1038 end:
1039   GNUNET_free_non_null (rd_new);
1040
1041   switch (res) {
1042     case GNUNET_SYSERR:
1043        /* failed to create the record */
1044        crc->res = GNUNET_SYSERR;
1045       break;
1046     case GNUNET_YES:
1047       /* database operations OK */
1048       if (GNUNET_YES == update)
1049       {
1050         /* we updated an existing record */
1051         crc->res = GNUNET_NO;
1052       }
1053       else
1054       {
1055         /* we created a new record */
1056         crc->res = GNUNET_YES;
1057       }
1058       break;
1059     case GNUNET_NO:
1060         /* identical entry existed, so we did nothing */
1061         crc->res = GNUNET_NO;
1062       break;
1063     default:
1064       break;
1065   }
1066   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
1067 }
1068
1069
1070 /**
1071  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1072  *
1073  * @param cls unused
1074  * @param client GNUNET_SERVER_Client sending the message
1075  * @param message message of type 'struct RecordCreateMessage'
1076  */
1077 static void
1078 handle_record_create (void *cls,
1079                       struct GNUNET_SERVER_Client *client,
1080                       const struct GNUNET_MessageHeader *message)
1081 {
1082   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1083   struct GNUNET_NAMESTORE_Client *nc;
1084   struct RecordCreateMessage *rp_msg;
1085   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1086   struct CreateRecordContext crc;
1087   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1088   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1089   struct RecordCreateResponseMessage rcr_msg;
1090   struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1091   struct GNUNET_HashCode long_hash;
1092   size_t name_len;
1093   size_t msg_size;
1094   size_t msg_size_exp;
1095   size_t rd_ser_len;
1096   size_t key_len;
1097   uint32_t rid = 0;
1098   char *pkey_tmp;
1099   char *name_tmp;
1100   char *rd_ser;
1101   int rd_count;
1102
1103   int res = GNUNET_SYSERR;
1104   crc.res = GNUNET_SYSERR;
1105
1106   if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1107   {
1108     GNUNET_break_op (0);
1109     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1110     return;
1111   }
1112
1113   nc = client_lookup(client);
1114   if (nc == NULL)
1115   {
1116     GNUNET_break_op (0);
1117     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1118     return;
1119   }
1120
1121   rp_msg = (struct RecordCreateMessage *) message;
1122   rid = ntohl (rp_msg->gns_header.r_id);
1123   name_len = ntohs (rp_msg->name_len);
1124   msg_size = ntohs (message->size);
1125   rd_count = ntohs (rp_msg->rd_count);
1126   rd_ser_len = ntohs (rp_msg->rd_len);
1127   key_len = ntohs (rp_msg->pkey_len);
1128   msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1129
1130   if (msg_size != msg_size_exp)
1131   {
1132     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1133     GNUNET_break_op (0);
1134     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1135     return;
1136   }
1137
1138   if ((name_len == 0) || (name_len > 256))
1139   {
1140     GNUNET_break_op (0);
1141     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1142     return;
1143   }
1144
1145   pkey_tmp = (char *) &rp_msg[1];
1146   name_tmp = &pkey_tmp[key_len];
1147   rd_ser = &name_tmp[name_len];
1148
1149   if (name_tmp[name_len -1] != '\0')
1150   {
1151     GNUNET_break_op (0);
1152     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1153     return;
1154   }
1155
1156   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1157
1158   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1159   if ((res != GNUNET_OK) || (rd_count != 1))
1160   {
1161     GNUNET_break_op (0);
1162     goto send;
1163   }
1164   /* Extracting and converting private key */
1165   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1166   GNUNET_assert (pkey != NULL);
1167   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1168   GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1169   GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1170
1171   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1172   {
1173     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash));
1174
1175     cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1176     cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1177     cc->pubkey = GNUNET_malloc(sizeof (pub));
1178     memcpy (cc->pubkey, &pub, sizeof(pub));
1179     cc->zone = pubkey_hash;
1180     GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1181   }
1182
1183   crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1184   crc.res = GNUNET_SYSERR;
1185   crc.pkey = pkey;
1186   crc.pubkey = &pub;
1187   crc.rd = rd;
1188   crc.name = name_tmp;
1189
1190   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1191
1192   /* Get existing records for name */
1193   res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
1194   if (res != GNUNET_SYSERR)
1195     res = GNUNET_OK;
1196   GNUNET_CRYPTO_rsa_key_free(pkey);
1197   pkey = NULL;
1198
1199   /* Send response */
1200 send:
1201   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1202   rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1203   rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1204   rcr_msg.gns_header.r_id = htonl (rid);
1205   if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1206     rcr_msg.op_result = htonl (GNUNET_YES);
1207   else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1208     rcr_msg.op_result = htonl (GNUNET_NO);
1209   else
1210     rcr_msg.op_result = htonl (GNUNET_SYSERR);
1211   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
1212
1213   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1214 }
1215
1216 /**
1217  * RemoveRecordContext
1218  *
1219  * Context for record remove operations passed from 'handle_record_remove' to
1220  * 'handle_record_remove_it' as closure
1221  */
1222 struct RemoveRecordContext
1223 {
1224   /**
1225    * Record to remove
1226    */
1227   struct GNUNET_NAMESTORE_RecordData *rd;
1228
1229   /**
1230    * Zone's private keys
1231    */
1232   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1233
1234   /**
1235    * Name to remove
1236    */
1237   int remove_name;
1238
1239   /**
1240    * 0 : Success
1241    * 1 : Could not find record to remove, empty result set
1242    * 2 : Could not find record to remove, record did not exist in result set
1243    * 3 : Could not remove records from database
1244    * 4 : Could not put records into database
1245    */
1246   uint16_t op_res;
1247 };
1248
1249 static void
1250 handle_record_remove_it (void *cls,
1251     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1252     struct GNUNET_TIME_Absolute expire,
1253     const char *name,
1254     unsigned int rd_count,
1255     const struct GNUNET_NAMESTORE_RecordData *rd,
1256     const struct GNUNET_CRYPTO_RsaSignature *signature)
1257 {
1258   struct RemoveRecordContext *rrc = cls;
1259   unsigned int c;
1260   int res;
1261   int found;
1262   unsigned int rd_count_new;
1263
1264   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
1265
1266   if (rd_count == 0)
1267   {
1268     /* Could not find record to remove */
1269     rrc->op_res = 1;
1270     return;
1271   }
1272
1273   /* Find record to remove */
1274   found = GNUNET_SYSERR;
1275   for (c = 0; c < rd_count; c++)
1276   {
1277     /*
1278     if (rd[c].flags != rrc->rd->flags)
1279        continue;*/
1280     if (rd[c].record_type != rrc->rd->record_type)
1281        continue;
1282     /*
1283     if (rd[c].data_size != rrc->rd->data_size)
1284        continue;
1285     GNUNET_break(0);
1286     if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1287         continue;
1288     GNUNET_break(0); */
1289     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1290     found = c;
1291     break;
1292   }
1293   if (GNUNET_SYSERR == found)
1294   {
1295     /* Could not find record to remove */
1296     rrc->op_res = 2;
1297     return;
1298   }
1299
1300   if (rd_count-1 == 0)
1301   {
1302     struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1303     GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1304     res = GSN_database->remove_records (GSN_database->cls,
1305                                         &pubkey_hash,
1306                                         name);
1307     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1308                 "No records left for name `%s', removing name\n",
1309                 name, res);
1310     if (GNUNET_OK != res)
1311     {
1312       /* Could not remove records from database */
1313       rrc->op_res = 3;
1314       return;
1315     }
1316     rrc->op_res = 0;
1317     return;
1318   }
1319
1320   rd_count_new = rd_count -1;
1321   struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1322
1323   unsigned int c2 = 0;
1324   for (c = 0; c < rd_count; c++)
1325   {
1326     if (c != found)
1327     {
1328       GNUNET_assert (c2 < rd_count_new);
1329       rd_new[c2] = rd[c];
1330       c2++;
1331     }
1332   }
1333
1334   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1335
1336   /* Create dummy signature */
1337   struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1338   memset (&dummy_signature, '\0', sizeof (dummy_signature));
1339
1340
1341   /* Put records */
1342   res = GSN_database->put_records(GSN_database->cls,
1343                                   zone_key,
1344                                   expire,
1345                                   name,
1346                                   rd_count_new, rd_new,
1347                                   &dummy_signature);
1348   if (GNUNET_OK != res)
1349   {
1350     /* Could not put records into database */
1351     rrc->op_res = 4;
1352     return;
1353   }
1354
1355   rrc->op_res = 0;
1356 }
1357
1358 /**
1359  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1360  *
1361  * @param cls unused
1362  * @param client GNUNET_SERVER_Client sending the message
1363  * @param message message of type 'struct RecordRemoveMessage'
1364  */
1365 static void
1366 handle_record_remove (void *cls,
1367                       struct GNUNET_SERVER_Client *client,
1368                       const struct GNUNET_MessageHeader *message)
1369 {
1370   struct GNUNET_NAMESTORE_Client *nc;
1371   const struct RecordRemoveMessage *rr_msg;
1372   struct RecordRemoveResponseMessage rrr_msg;
1373   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1374   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1375   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1376   struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1377   struct GNUNET_HashCode long_hash;
1378   const char *pkey_tmp;
1379   const char *name_tmp;
1380   const char *rd_ser;
1381   size_t key_len;
1382   size_t name_len;
1383   size_t rd_ser_len;
1384   size_t msg_size;
1385   size_t msg_size_exp = 0;
1386   uint32_t rd_count;
1387   uint32_t rid;
1388
1389   int res = GNUNET_SYSERR;
1390
1391   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1392   if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1393   {
1394     GNUNET_break_op (0);
1395     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1396     return;
1397   }
1398
1399   nc = client_lookup(client);
1400   if (nc == NULL)
1401   {
1402     GNUNET_break_op (0);
1403     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1404     return;
1405   }
1406
1407   rr_msg = (const struct RecordRemoveMessage *) message;
1408   rid = ntohl (rr_msg->gns_header.r_id);
1409   name_len = ntohs (rr_msg->name_len);
1410   rd_ser_len = ntohs (rr_msg->rd_len);
1411   rd_count = ntohs (rr_msg->rd_count);
1412   key_len = ntohs (rr_msg->pkey_len);
1413   msg_size = ntohs (message->size);
1414
1415   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1416   {
1417     GNUNET_break_op (0);
1418     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1419     return;
1420   }
1421
1422   if ((name_len >=256) || (name_len == 0))
1423   {
1424     GNUNET_break_op (0);
1425     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1426     return;
1427   }
1428
1429   msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1430   if (msg_size != msg_size_exp)
1431   {
1432     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1433     GNUNET_break_op (0);
1434     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1435     return;
1436   }
1437
1438   pkey_tmp = (const char *) &rr_msg[1];
1439   name_tmp = &pkey_tmp[key_len];
1440   rd_ser = &name_tmp[name_len];
1441
1442
1443   if ((name_len == 0) || (name_len > 256))
1444   {
1445     GNUNET_break_op (0);
1446     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1447     return;
1448   }
1449
1450   if (name_tmp[name_len -1] != '\0')
1451   {
1452     GNUNET_break_op (0);
1453     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1454     return;
1455   }
1456
1457   /* Extracting and converting private key */
1458   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1459   GNUNET_assert (pkey != NULL);
1460   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1461   GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1462   GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1463
1464   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1465   {
1466     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1467                 "Received new private key for zone `%s'\n",
1468                 GNUNET_short_h2s(&pubkey_hash));
1469     cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1470     cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1471     cc->pubkey = GNUNET_malloc(sizeof (pub));
1472     memcpy (cc->pubkey, &pub, sizeof(pub));
1473     cc->zone = pubkey_hash;
1474
1475     GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1476   }
1477
1478
1479   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1480   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1481   if ((res != GNUNET_OK) || (rd_count > 1))
1482   {
1483     GNUNET_break_op (0);
1484     goto send;
1485   }
1486
1487   if (0 == rd_count)
1488   {
1489     /* remove the whole name and all records */
1490     /* Database operation */
1491     res = GSN_database->remove_records (GSN_database->cls,
1492                                          &pubkey_hash,
1493                                          name_tmp);
1494     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1495         name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1496
1497     if (GNUNET_OK != res)
1498       /* Could not remove entry from database */
1499       res = 4;
1500     else
1501       res = 0;
1502   }
1503   else
1504   {
1505     /* remove a single record */
1506     struct RemoveRecordContext rrc;
1507     rrc.rd = rd;
1508     rrc.pkey = pkey;
1509
1510     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1511
1512     /* Database operation */
1513     res = GSN_database->iterate_records (GSN_database->cls,
1514                                          &pubkey_hash,
1515                                          name_tmp,
1516                                          0,
1517                                          handle_record_remove_it, &rrc);
1518
1519     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1520         name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1521     res = rrc.op_res;
1522   }
1523   /* Send response */
1524 send:
1525   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1526   rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1527   rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1528   rrr_msg.gns_header.r_id = htonl (rid);
1529   rrr_msg.op_result = htonl (res);
1530   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1531
1532   GNUNET_CRYPTO_rsa_key_free (pkey);
1533
1534   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1535 }
1536
1537 /**
1538  * ZoneToNameCtx
1539  *
1540  * Context for record remove operations passed from 'handle_zone_to_name' to
1541  * 'handle_zone_to_name_it' as closure
1542  */
1543 struct ZoneToNameCtx
1544 {
1545   /**
1546    * Namestore client
1547    */
1548   struct GNUNET_NAMESTORE_Client *nc;
1549
1550   /**
1551    * Request id
1552    */
1553   uint32_t rid;
1554 };
1555
1556
1557 /**
1558  * Zone to name iterator
1559  *
1560  * @param cls struct ZoneToNameCtx *
1561  * @param zone_key the zone key
1562  * @param expire expiration date
1563  * @param name name
1564  * @param rd_count number of records
1565  * @param rd record data
1566  * @param signature signature
1567  */
1568 static void
1569 handle_zone_to_name_it (void *cls,
1570     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1571     struct GNUNET_TIME_Absolute expire,
1572     const char *name,
1573     unsigned int rd_count,
1574     const struct GNUNET_NAMESTORE_RecordData *rd,
1575     const struct GNUNET_CRYPTO_RsaSignature *signature)
1576 {
1577   struct ZoneToNameCtx *ztn_ctx = cls;
1578   struct ZoneToNameResponseMessage *ztnr_msg;
1579   int16_t res = GNUNET_SYSERR;
1580   uint16_t name_len = 0;
1581   uint16_t rd_ser_len = 0 ;
1582   int32_t contains_sig = 0;
1583   size_t msg_size = 0;
1584
1585   char *rd_ser = NULL;
1586   char *name_tmp;
1587   char *rd_tmp;
1588   char *sig_tmp;
1589
1590   if ((zone_key != NULL) && (name != NULL))
1591   {
1592     /* found result */
1593     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1594     res = GNUNET_YES;
1595     name_len = strlen (name) +1;
1596   }
1597   else
1598   {
1599     /* no result found */
1600     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1601     res = GNUNET_NO;
1602     name_len = 0;
1603   }
1604
1605   if (rd_count > 0)
1606   {
1607     rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1608     rd_ser = GNUNET_malloc (rd_ser_len);
1609     GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1610   }
1611   else
1612     rd_ser_len = 0;
1613
1614   if (signature != NULL)
1615     contains_sig = GNUNET_YES;
1616   else
1617     contains_sig = GNUNET_NO;
1618
1619
1620
1621   msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1622   ztnr_msg = GNUNET_malloc (msg_size);
1623
1624   name_tmp = (char *) &ztnr_msg[1];
1625   rd_tmp = &name_tmp[name_len];
1626   sig_tmp = &rd_tmp[rd_ser_len];
1627
1628   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1629   ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1630   ztnr_msg->gns_header.header.size = htons (msg_size);
1631   ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1632   ztnr_msg->res = htons (res);
1633   ztnr_msg->rd_len = htons (rd_ser_len);
1634   ztnr_msg->rd_count = htons (rd_count);
1635   ztnr_msg->name_len = htons (name_len);
1636   ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1637   if (zone_key != NULL)
1638     ztnr_msg->zone_key = *zone_key;
1639   else
1640     memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1641
1642   if ((name_len > 0) && (name != NULL))
1643     memcpy (name_tmp, name, name_len);
1644
1645   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);
1646   if ((rd_ser_len > 0) && (rd_ser != NULL))
1647     memcpy (rd_tmp, rd_ser, rd_ser_len);
1648   if ((GNUNET_YES == contains_sig) && (signature != NULL))
1649     memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1650
1651   GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1652   GNUNET_free (ztnr_msg);
1653   GNUNET_free_non_null (rd_ser);
1654 }
1655
1656 /**
1657  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1658  *
1659  * @param cls unused
1660  * @param client GNUNET_SERVER_Client sending the message
1661  * @param message message of type 'struct ZoneToNameMessage'
1662  */
1663 static void
1664 handle_zone_to_name (void *cls,
1665                      struct GNUNET_SERVER_Client *client,
1666                      const struct GNUNET_MessageHeader *message)
1667 {
1668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1669   struct GNUNET_NAMESTORE_Client *nc;
1670   struct ZoneToNameMessage *ztn_msg;
1671   struct ZoneToNameCtx ztn_ctx;
1672   size_t msg_size = 0;
1673   uint32_t rid = 0;
1674
1675   if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1676   {
1677     GNUNET_break_op (0);
1678     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1679     return;
1680   }
1681
1682   nc = client_lookup(client);
1683   if (nc == NULL)
1684   {
1685     GNUNET_break_op (0);
1686     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1687     return;
1688   }
1689
1690   ztn_msg = (struct ZoneToNameMessage *) message;
1691
1692   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1693   {
1694     GNUNET_break_op (0);
1695     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1696     return;
1697   }
1698
1699   rid = ntohl (ztn_msg->gns_header.r_id);
1700
1701   ztn_ctx.rid = rid;
1702   ztn_ctx.nc = nc;
1703
1704   struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1705   GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1706   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1707       (char *) &z_tmp,
1708       GNUNET_short_h2s (&ztn_msg->value_zone));
1709
1710   GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1711
1712   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1713 }
1714
1715
1716 /**
1717  * Copy record, data has to be free'd separetely
1718  *
1719  * @param src source record
1720  * @param dest destination record
1721  */
1722 static void
1723 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1724 {
1725
1726   memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1727   dest->data = GNUNET_malloc (src->data_size);
1728   memcpy ((void *) dest->data, src->data, src->data_size);
1729 }
1730
1731
1732 /**
1733  * ZoneIterationProcResult
1734  *
1735  * Context for record remove operations passed from
1736  * 'find_next_zone_iteration_result' to 'zone_iteraterate_proc' as closure
1737  */
1738 struct ZoneIterationProcResult
1739 {
1740   /**
1741    * The zone iteration handle
1742    */
1743   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1744
1745   /**
1746    * Iteration result: iteration done?
1747    */
1748   int res_iteration_finished;
1749
1750   /**
1751    * Iteration result: number of records included
1752    */
1753   int records_included;
1754
1755   /**
1756    * Iteration result: is a valid signature included?
1757    */
1758   int has_signature;
1759
1760   /**
1761    * Name
1762    */
1763   char *name;
1764
1765   /**
1766    * Zone hash
1767    */
1768   struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1769
1770   /**
1771    * Record data
1772    */
1773   struct GNUNET_NAMESTORE_RecordData *rd;
1774
1775   /**
1776    * Zone's public key
1777    */
1778   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1779
1780   /**
1781    * Signature
1782    */
1783   struct GNUNET_CRYPTO_RsaSignature signature;
1784
1785   /**
1786    * Expiration date
1787    */
1788   struct GNUNET_TIME_Absolute expire;
1789 };
1790
1791
1792 /**
1793  * Process results for zone iteration from database
1794  *
1795  * @param cls struct ZoneIterationProcResult *proc
1796  * @param zone_key the zone key
1797  * @param expire expiration time
1798  * @param name name
1799  * @param rd_count number of records for this name
1800  * @param rd record data
1801  * @param signature block signature
1802  */
1803
1804 static void
1805 zone_iteraterate_proc (void *cls,
1806                        const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1807                        struct GNUNET_TIME_Absolute expire,
1808                        const char *name,
1809                        unsigned int rd_count,
1810                        const struct GNUNET_NAMESTORE_RecordData *rd,
1811                        const struct GNUNET_CRYPTO_RsaSignature *signature)
1812 {
1813   struct ZoneIterationProcResult *proc = cls;
1814   struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1815   struct GNUNET_CRYPTO_RsaSignature *new_signature;
1816   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1817   struct GNUNET_CRYPTO_ShortHashCode hash;
1818   struct GNUNET_HashCode long_hash;
1819   struct GNUNET_TIME_Absolute e;
1820   unsigned int rd_count_filtered  = 0;
1821   int include;
1822   int c;
1823
1824   proc->res_iteration_finished = GNUNET_NO;
1825   proc->records_included = 0;
1826
1827   if ((zone_key == NULL) && (name == NULL))
1828   {
1829     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1830     proc->res_iteration_finished = GNUNET_YES;
1831     proc->rd = NULL;
1832     proc->name = NULL;
1833   }
1834   else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1835   {
1836     rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1837     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1838     for (c = 0; c < rd_count; c++)
1839     {
1840       include = GNUNET_YES;
1841       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1842           c, rd[c].flags, proc->zi->must_have_flags);
1843       /* Checking must have flags */
1844       if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1845       {
1846         /* Include */
1847         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1848       }
1849       else
1850       {
1851         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1852         include = GNUNET_NO;
1853       }
1854
1855       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1856           c, rd[c].flags, proc->zi->must_not_have_flags);
1857       if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1858       {
1859         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1860         include = GNUNET_NO;
1861       }
1862       else
1863       {
1864         /* Include */
1865         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1866       }
1867       if (GNUNET_YES == include)
1868       {
1869         copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1870         rd_count_filtered++;
1871       }
1872
1873     }
1874     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1875
1876     proc->records_included = rd_count_filtered;
1877     if (0 == rd_count_filtered)
1878     {
1879       GNUNET_free (rd_filtered);
1880       rd_filtered = NULL;
1881     }
1882     proc->rd = rd_filtered;
1883     proc->name = GNUNET_strdup(name);
1884     memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1885
1886     /* Signature */
1887     proc->has_signature = GNUNET_NO;
1888     GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1889     GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1890     proc->zone_hash = hash;
1891
1892     if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1893     {
1894       cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1895       e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1896       proc->expire = e;
1897       new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1898       GNUNET_assert (signature != NULL);
1899       proc->signature = (*new_signature);
1900       GNUNET_free (new_signature);
1901       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1902           name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1903       proc->has_signature = GNUNET_YES;
1904     }
1905     else if (rd_count_filtered == rd_count)
1906     {
1907       proc->expire = expire;
1908       if (NULL != signature)
1909       {
1910         proc->signature = (*signature);
1911         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1912             name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1913         proc->has_signature = GNUNET_YES;
1914       }
1915       else
1916       {
1917         memset (&proc->signature, '\0', sizeof (proc->signature));
1918         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1919       }
1920     }
1921   }
1922   else
1923   {
1924     GNUNET_break (0);
1925     return;
1926   }
1927
1928 }
1929
1930
1931 /**
1932  *  Find next zone iteration result in database
1933  *  @param proc the zone iteration processing to use
1934  */
1935 static void
1936 find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1937 {
1938
1939   struct GNUNET_CRYPTO_ShortHashCode *zone;
1940
1941   if (GNUNET_YES == proc->zi->has_zone)
1942     zone = &proc->zi->zone;
1943   else
1944     zone = NULL;
1945
1946   do
1947   {
1948     GSN_database->iterate_records (GSN_database->cls, zone , NULL, proc->zi->offset, &zone_iteraterate_proc, proc);
1949     proc->zi->offset++;
1950   }
1951   while ((proc->records_included == 0) && (GNUNET_NO == proc->res_iteration_finished));
1952 }
1953
1954
1955 /**
1956  * Send zone iteration result to client
1957  * @param proc the zone iteration processing result to send
1958  */
1959 static void
1960 send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1961 {
1962   struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1963
1964   if (GNUNET_YES == proc->res_iteration_finished)
1965   {
1966     struct ZoneIterationResponseMessage zir_msg;
1967     if (zi->has_zone == GNUNET_YES)
1968       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_short_h2s(&zi->zone));
1969     else
1970       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n");
1971
1972     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE");
1973     zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1974     zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1975     zir_msg.gns_header.r_id = htonl(zi->request_id);
1976     zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
1977     zir_msg.name_len = htons (0);
1978     zir_msg.reserved = htons (0);
1979     zir_msg.rd_count = htons (0);
1980     zir_msg.rd_len = htons (0);
1981     memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key));
1982     memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature));
1983     GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1984
1985     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1986     GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1987     GNUNET_free (zi);
1988     return;
1989   }
1990   else
1991   {
1992     GNUNET_assert (proc->records_included > 0);
1993
1994     struct ZoneIterationResponseMessage *zir_msg;
1995     if (zi->has_zone == GNUNET_YES)
1996       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n",
1997           proc->name, GNUNET_short_h2s(&zi->zone));
1998     if (zi->has_zone == GNUNET_NO)
1999       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n",
2000           proc->name);
2001
2002     size_t name_len;
2003     size_t rd_ser_len;
2004     size_t msg_size;
2005     char *name_tmp;
2006     char *rd_tmp;
2007     name_len = strlen (proc->name) +1;
2008
2009     rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);
2010     char rd_ser[rd_ser_len];
2011     GNUNET_NAMESTORE_records_serialize(proc->records_included, proc->rd, rd_ser_len, rd_ser);
2012     msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
2013     zir_msg = GNUNET_malloc(msg_size);
2014
2015     name_tmp = (char *) &zir_msg[1];
2016     rd_tmp = &name_tmp[name_len];
2017
2018     zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
2019     zir_msg->gns_header.header.size = htons (msg_size);
2020     zir_msg->gns_header.r_id = htonl(zi->request_id);
2021     zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire);
2022     zir_msg->reserved = htons (0);
2023     zir_msg->name_len = htons (name_len);
2024     zir_msg->rd_count = htons (proc->records_included);
2025     zir_msg->rd_len = htons (rd_ser_len);
2026     zir_msg->signature = proc->signature;
2027     zir_msg->public_key = proc->zone_key;
2028     memcpy (name_tmp, proc->name, name_len);
2029     memcpy (rd_tmp, rd_ser, rd_ser_len);
2030
2031     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size);
2032     GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) zir_msg, GNUNET_NO);
2033     GNUNET_free (zir_msg);
2034   }
2035 }
2036
2037
2038 /**
2039  * Clean up after zone iteration
2040  * @param proc the zone iteration processor
2041  */
2042 static void
2043 clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
2044 {
2045   int c;
2046   GNUNET_free_non_null (proc->name);
2047   for (c = 0; c < proc->records_included; c++)
2048   {
2049     GNUNET_free ((void *) proc->rd[c].data);
2050   }
2051   GNUNET_free_non_null (proc->rd);
2052   proc->name = NULL;
2053   proc->rd = NULL;
2054 }
2055
2056
2057 /**
2058  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
2059  *
2060  * @param cls unused
2061  * @param client GNUNET_SERVER_Client sending the message
2062  * @param message message of type 'struct ZoneIterationStartMessage'
2063  */
2064 static void
2065 handle_iteration_start (void *cls,
2066                         struct GNUNET_SERVER_Client *client,
2067                         const struct GNUNET_MessageHeader *message)
2068 {
2069   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2070
2071   struct ZoneIterationStartMessage *zis_msg = (struct ZoneIterationStartMessage *) message;
2072   struct GNUNET_NAMESTORE_Client *nc;
2073   struct GNUNET_NAMESTORE_ZoneIteration *zi;
2074   struct GNUNET_CRYPTO_ShortHashCode dummy;
2075   struct ZoneIterationProcResult proc;
2076
2077   nc = client_lookup(client);
2078   if (nc == NULL)
2079   {
2080     GNUNET_break_op (0);
2081     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2082     return;
2083   }
2084
2085   zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2086   zi->request_id = ntohl (zis_msg->gns_header.r_id);
2087   zi->offset = 0;
2088   zi->client = nc;
2089   zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2090   zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2091
2092   memset (&dummy, '\0', sizeof (dummy));
2093   if (0 == memcmp (&dummy, &zis_msg->zone, sizeof (dummy)))
2094   {
2095     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2096     zi->zone = zis_msg->zone;
2097     zi->has_zone = GNUNET_NO;
2098   }
2099   else
2100   {
2101     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over zone  `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2102     zi->zone = zis_msg->zone;
2103     zi->has_zone = GNUNET_YES;
2104   }
2105
2106   GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2107
2108   proc.zi = zi;
2109   find_next_zone_iteration_result (&proc);
2110   if (GNUNET_YES == proc.res_iteration_finished)
2111   {
2112     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
2113   }
2114   else if (proc.records_included != 0)
2115   {
2116     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
2117   }
2118   send_zone_iteration_result (&proc);
2119   clean_up_zone_iteration_result (&proc);
2120
2121   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2122 }
2123
2124
2125 /**
2126  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2127  *
2128  * @param cls unused
2129  * @param client GNUNET_SERVER_Client sending the message
2130  * @param message message of type 'struct ZoneIterationStopMessage'
2131  */
2132 static void
2133 handle_iteration_stop (void *cls,
2134                        struct GNUNET_SERVER_Client *client,
2135                        const struct GNUNET_MessageHeader *message)
2136 {
2137   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
2138
2139   struct GNUNET_NAMESTORE_Client *nc;
2140   struct GNUNET_NAMESTORE_ZoneIteration *zi;
2141   struct ZoneIterationStopMessage *zis_msg;
2142   uint32_t rid;
2143
2144   nc = client_lookup(client);
2145   if (nc == NULL)
2146   {
2147     GNUNET_break_op (0);
2148     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2149     return;
2150   }
2151
2152   zis_msg = (struct ZoneIterationStopMessage *) message;
2153   rid = ntohl (zis_msg->gns_header.r_id);
2154   for (zi = nc->op_head; zi != NULL; zi = zi->next)
2155   {
2156     if (zi->request_id == rid)
2157       break;
2158   }
2159   if (zi == NULL)
2160   {
2161     GNUNET_break_op (0);
2162     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2163     return;
2164   }
2165
2166   GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
2167   if (GNUNET_YES == zi->has_zone)
2168     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_short_h2s (&zi->zone));
2169   else
2170     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration all zones\n");
2171   GNUNET_free (zi);
2172
2173   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2174 }
2175
2176
2177 /**
2178  * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2179  *
2180  * @param cls unused
2181  * @param client GNUNET_SERVER_Client sending the message
2182  * @param message message of type 'struct ZoneIterationNextMessage'
2183  */
2184 static void
2185 handle_iteration_next (void *cls,
2186                        struct GNUNET_SERVER_Client *client,
2187                        const struct GNUNET_MessageHeader *message)
2188 {
2189   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2190
2191   struct GNUNET_NAMESTORE_Client *nc;
2192   struct GNUNET_NAMESTORE_ZoneIteration *zi;
2193   struct ZoneIterationNextMessage *zis_msg;
2194   uint32_t rid;
2195
2196   nc = client_lookup(client);
2197   if (nc == NULL)
2198   {
2199     GNUNET_break_op (0);
2200     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2201     return;
2202   }
2203
2204   zis_msg = (struct ZoneIterationNextMessage *) message;
2205   rid = ntohl (zis_msg->gns_header.r_id);
2206   for (zi = nc->op_head; zi != NULL; zi = zi->next)
2207   {
2208     if (zi->request_id == rid)
2209       break;
2210   }
2211   if (zi == NULL)
2212   {
2213     GNUNET_break_op (0);
2214     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2215     return;
2216   }
2217
2218   struct ZoneIterationProcResult proc;
2219   proc.zi = zi;
2220
2221   find_next_zone_iteration_result (&proc);
2222   if (GNUNET_YES == proc.res_iteration_finished)
2223   {
2224     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
2225   }
2226   else if (proc.records_included != 0)
2227   {
2228     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
2229   }
2230   send_zone_iteration_result (&proc);
2231   clean_up_zone_iteration_result (&proc);
2232
2233   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2234 }
2235
2236
2237 /**
2238  * Load zone keys from directory by reading all .zkey files in this directory
2239  *
2240  * @param cls int * 'counter' to store the number of files found
2241  * @param filename directory to scan
2242  * @return GNUNET_OK to continue
2243  */
2244 static int
2245 zonekey_file_it (void *cls, const char *filename)
2246 {
2247   struct GNUNET_HashCode long_hash;
2248   int *counter = cls;
2249    if ((filename != NULL) && (NULL != strstr(filename, ".zkey")))
2250    {
2251      struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2252      struct GNUNET_NAMESTORE_CryptoContainer *c;
2253      privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
2254      if (privkey == NULL)
2255        return GNUNET_OK;
2256
2257      c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
2258      c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2259      c->privkey = privkey;
2260      GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
2261      GNUNET_CRYPTO_short_hash(c->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &c->zone);
2262
2263      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
2264      GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
2265      GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2266      (*counter) ++;
2267    }
2268    return GNUNET_OK;
2269 }
2270
2271
2272 /**
2273  * Process namestore requests.
2274  *
2275  * @param cls closure
2276  * @param server the initialized server
2277  * @param cfg configuration to use
2278  */
2279 static void
2280 run (void *cls, struct GNUNET_SERVER_Handle *server,
2281      const struct GNUNET_CONFIGURATION_Handle *cfg)
2282 {
2283   char *database;
2284   int counter = 0;
2285   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2286
2287   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2288     {&handle_start, NULL,
2289      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2290     {&handle_lookup_name, NULL,
2291      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2292     {&handle_record_put, NULL,
2293     GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2294     {&handle_record_create, NULL,
2295      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2296     {&handle_record_remove, NULL,
2297      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2298     {&handle_zone_to_name, NULL,
2299       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
2300     {&handle_iteration_start, NULL,
2301      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
2302     {&handle_iteration_next, NULL,
2303      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
2304      {&handle_iteration_stop, NULL,
2305       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0},
2306     {NULL, NULL, 0, 0}
2307   };
2308
2309   GSN_cfg = cfg;
2310
2311   /* Load private keys from disk */
2312   if (GNUNET_OK !=
2313       GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", "zonefile_directory",
2314                                              &zonefile_directory))
2315   {
2316     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No directory to load zonefiles specified in configuration\n"));
2317     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2318     return;
2319   }
2320
2321   if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2322   {
2323     if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2324     {
2325       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Creating directory `%s' for zone files failed!\n"), zonefile_directory);
2326       GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2327       return;
2328     }
2329     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created directory `%s' for zone files\n", zonefile_directory);
2330   }
2331
2332   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scanning directory `%s' for zone files\n", zonefile_directory);
2333   zonekeys = GNUNET_CONTAINER_multihashmap_create (10);
2334   GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2335   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u zone files\n", counter);
2336
2337   /* Loading database plugin */
2338   if (GNUNET_OK !=
2339       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2340                                              &database))
2341     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2342
2343   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2344   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2345   GNUNET_free (database);
2346   if (GSN_database == NULL)
2347   {
2348     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
2349         db_lib_name);
2350     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2351     return;
2352   }
2353
2354   /* Configuring server handles */
2355   GNUNET_SERVER_add_handlers (server, handlers);
2356   snc = GNUNET_SERVER_notification_context_create (server, 16);
2357   GNUNET_SERVER_disconnect_notify (server,
2358                                    &client_disconnect_notification,
2359                                    NULL);
2360
2361   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2362                                 NULL);
2363
2364 }
2365
2366
2367 /**
2368  * The main function for the template service.
2369  *
2370  * @param argc number of arguments from the command line
2371  * @param argv command line arguments
2372  * @return 0 ok, 1 on error
2373  */
2374 int
2375 main (int argc, char *const *argv)
2376 {
2377   return (GNUNET_OK ==
2378           GNUNET_SERVICE_run (argc, argv, "namestore",
2379                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2380 }
2381
2382 /* end of gnunet-service-namestore.c */
2383