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