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